{"id":2779,"date":"2025-11-22T10:59:10","date_gmt":"2025-11-22T01:59:10","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=2779"},"modified":"2025-11-23T22:37:26","modified_gmt":"2025-11-23T13:37:26","slug":"kotlin-bottomtabmenu","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2025\/11\/22\/kotlin-bottomtabmenu\/","title":{"rendered":"[Kotlin]\ud558\ub2e8\ud0ed\uba54\ub274\/BottomTabMenu"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \ud558\ub2e8 \ud0ed \uba54\ub274,\ub4dc\ub86d\ub2e4\uc6b4 \uba54\ub274\uc5d0 \ub300\ud55c \uc124\uba85\uc785\ub2c8\ub2e4.<br>Description of the bottom tab menu and drop-down menu.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc2a4\ud06c\ub9b0 \ud30c\uc77c\uc740 \ub2e4\ub978 \ucf54\ud2c0\ub9b0 \ud30c\uc77c\ub85c \ubd84\ub9ac\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.<br>Screen file is separated into a different Kotlin file.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \ub098\uba38\uc9c0 \uc124\uba85\uc740 \ucf54\ub4dc \uc8fc\uc11d\uc744 \ucc38\uc870 \ud558\uc138\uc694<br>Please refer to the code comments for the rest of the explanation.<\/p>\n\n\n\n<p>\u2714\ufe0f MainActivity.kt<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.freelifemakers.bottomnavigationbar\n\n\nimport android.os.Bundle\nimport androidx.activity.ComponentActivity\nimport androidx.activity.compose.setContent\nimport androidx.activity.enableEdgeToEdge\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material.icons.Icons\nimport androidx.compose.material.icons.filled.Home\nimport androidx.compose.material.icons.filled.Menu\nimport androidx.compose.material.icons.filled.MoreVert\nimport androidx.compose.material.icons.filled.Search\nimport androidx.compose.material.icons.filled.Settings\nimport androidx.compose.material3.CenterAlignedTopAppBar\nimport androidx.compose.material3.DropdownMenu\nimport androidx.compose.material3.DropdownMenuItem\nimport androidx.compose.material3.ExperimentalMaterial3Api\nimport androidx.compose.material3.Icon\nimport androidx.compose.material3.IconButton\nimport androidx.compose.material3.NavigationBar\nimport androidx.compose.material3.NavigationBarItem\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.runtime.getValue\nimport androidx.compose.runtime.mutableStateOf\nimport androidx.compose.runtime.remember\nimport androidx.compose.runtime.setValue\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.vector.ImageVector\nimport androidx.compose.ui.tooling.preview.Preview\nimport androidx.navigation.NavHostController\nimport androidx.navigation.compose.currentBackStackEntryAsState\nimport androidx.navigation.compose.rememberNavController\nimport com.freelifemakers.bottomnavigationbar.ui.theme.BottomNavigationBarTheme\nimport androidx.navigation.compose.NavHost\nimport androidx.navigation.compose.composable\n\/\/ screen\nimport com.freelifemakers.bottomnavigationbar.ui.screens.HomeScreen\nimport com.freelifemakers.bottomnavigationbar.ui.screens.SearchScreen\nimport com.freelifemakers.bottomnavigationbar.ui.screens.SettingsScreen\n\n\nclass MainActivity : ComponentActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        enableEdgeToEdge()\n        setContent {\n            BottomNavigationBarTheme {\n                \/\/ MainScreen \ucef4\ud3ec\uc800\ube14\uc744 \ud638\ucd9c\ud558\uc5ec \uc804\uccb4 \ud654\uba74 \uad6c\uc870\ub97c \ub2f4\ub2f9\n                \/\/ Call the MainScreen composable to take charge of the entire screen structure\n                MainScreen()\n            }\n        }\n    }\n}\n\n\/\/ \uac01 \ud654\uba74\uc758 \uacbd\ub85c(Route)\ub97c \uc815\uc758\ud558\ub294 sealed class\n\/\/ sealed class : \ubd09\uc778 \ud074\ub798\uc2a4 \uac19\uc740 \ud30c\uc77c \ub0b4\uc5d0\uc11c\ub9cc \uc0c1\uc18d\uc744 \ud5c8\uc6a9\ud568.\n\/\/ Sealed class that defines the route for each screen\n\/\/ Sealed class: Inheritance is allowed only within the same file as the sealed class.\nsealed class Screen(val route: String, val title: String, val icon: ImageVector) {\n    object Home : Screen(\"home\", \"\ud648\/Home\", Icons.Filled.Home)\n    object Search : Screen(\"search\", \"\uac80\uc0c9\/Search\", Icons.Filled.Search)\n    object Settings : Screen(\"settings\", \"\uc124\uc815\/Settings\", Icons.Filled.Settings)\n}\n\n\/\/ \uc804\uccb4 \ud654\uba74 \ub808\uc774\uc544\uc6c3\uacfc \ud558\ub2e8 \ubc14\ub97c \uad6c\uc131\ud558\ub294 \uba54\uc778 \ucef4\ud3ec\uc800\ube14\n\/\/ \uc804\uccb4 \ud654\uba74 \ub808\uc774\uc544\uc6c3 \ubc0f \ub124\ube44\uac8c\uc774\uc158\uc744 \ub2f4\ub2f9\ud558\ub294 \uba54\uc778 \ucef4\ud3ec\uc800\ube14\n\/\/ Main composable that configures the full-screen layout and bottom bar\n\/\/ Main composable that handles the full-screen layout and navigation\n@Composable\nfun MainScreen() {\n    \/\/ NavController \uc0dd\uc131 \ubc0f \uae30\uc5b5 (Navigation \uc0c1\ud0dc \uad00\ub9ac)\n    \/\/ Create and remember NavController (manage navigation state)\n    val navController = rememberNavController()\n\n    \/\/ \ud558\ub2e8 \uba54\ub274\uc5d0 \ud45c\uc2dc\ub420 \ud56d\ubaa9 \ub9ac\uc2a4\ud2b8\n    \/\/ List of items to be displayed in the bottom menu\n    val bottomNavItems = listOf(Screen.Home, Screen.Search, Screen.Settings)\n\n    \/\/ -- \uc0c1\ub2e8 \uc571\ubc14\ub97c \uc704\ud55c \uc124\uc815 \/ Settings for the top app bar\n    \/\/  \ud604\uc7ac \ud654\uba74\uc815\ubcf4 \uac00\uc838\uc624\uae30 : \ud604\uc7ac \ubc31 \uc2a4\ud0dd \ud56d\ubaa9\uc744 \uac00\uc838\uc640\uc11c \ud604\uc7ac \ud654\uba74\uc758 \uc81c\ubaa9\uc744 \ud30c\uc545\n    \/\/ Get current screen information: Get the current back stack item and determine the title of the current screen.\n    val navBackStackEntry by navController.currentBackStackEntryAsState()\n\n    \/\/  \ud604\uc7ac \ud654\uba74\uc815\ubcf4\uc640 \ub9ac\uc2a4\ud2b8 \ub124\uc784\uacfc \uc77c\uce58\ud558\ub294\uc9c0 \ud655\uc778 ,\uc5c6\ub2e4\uba74 Home\uc73c\ub85c \uc124\uc815\n    \/\/ Check if the current screen information matches the list name, if not, set it to Home\n    val currentScreen = bottomNavItems.find { it.route == navBackStackEntry?.destination?.route } ?: Screen.Home\n\n    \/\/ Scaffold\ub294 \uc571 \ud654\uba74\uc758 \ubf08\ub300 \ub808\uc774\uc544\uc6c3\uc744 \uad00\ub9ac\ud558\uace0, \uc0c1\ub2e8\/\ud558\ub2e8 \ubc14, \ucf58\ud150\uce20, \ud328\ub529\uae4c\uc9c0 \uc790\ub3d9\uc73c\ub85c \uc870\uc815\ud574 \uc8fc\ub294 \ucee8\ud14c\uc774\ub108\uc785\ub2c8\ub2e4.\n    \/\/ Scaffold is a container that manages the skeleton layout of the app screen and automatically adjusts the top\/bottom bars, content, and padding.\n    Scaffold(\n        modifier = Modifier.fillMaxSize(),\n        \/\/ topBar \ud30c\ub77c\ubbf8\ud130\uc5d0 TopAppBar \ucef4\ud3ec\uc800\ube14 \ucd94\uac00\n        \/\/ Add TopAppBar composable to topBar parameter\n        topBar = {\n            MyTopAppBar(title = currentScreen.title)\n        },\n        bottomBar = {\n            \/\/ MyBottomNavigationBar \ub300\uc2e0 NavigationBar \ucef4\ud3ec\uc800\ube14\uc744 \uc9c1\uc811 \uc0ac\uc6a9\n            \/\/ Use NavigationBar composable directly instead of MyBottomNavigationBar\n            MyBottomNavigationBar(\n                navController = navController,\n                items = bottomNavItems\n            )\n        }\n    ) { innerPadding -&gt;\n\n        \/\/ \ub124\ube44\uac8c\uc774\uc158 \ud638\uc2a4\ud2b8 (\uc2e4\uc81c \ud654\uba74\uc774 \ubc14\ub00c\ub294 \uc601\uc5ed) \/ content\uc601\uc5ed\n        \/\/ Navigation host (area where the actual screen changes) \/ content area\n        AppNavigation(\n            navController = navController,\n            modifier = Modifier.padding(innerPadding) \/\/ \ud328\ub529 \uc801\uc6a9 \/ Apply padding\n        )\n    }\n}\n\n\/\/ \uc0c1\ub2e8 Navigation Bar \ucef4\ud3ec\uc800\ube14\n\/\/ TopAppBar \uad00\ub828 API \uc0ac\uc6a9 \uc2dc \ud544\uc694\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.(\uc2e4\ud5d8\uc801 \uae30\ub2a5)\n\/\/ Top Navigation Bar composable\n\/\/ May be required when using TopAppBar-related APIs. (Experimental feature)\n@OptIn(ExperimentalMaterial3Api::class)\n@Composable\nfun MyTopAppBar(title: String) {\n\n    var expandedLeft by remember { mutableStateOf(false) }\n    var expandedRight by remember { mutableStateOf(false) }\n\n    Box {\n        CenterAlignedTopAppBar(\n            title = { Text(text = title) },\n\n            \/\/ \uc67c\ucabd \ud584\ubc84\uac70 \uba54\ub274 \/ Left hamburger menu\n            navigationIcon = {\n                Box {\n                    IconButton(onClick = {\n                        expandedLeft = true\n                        expandedRight = false\n                    }) {\n                        Icon(\n                            imageVector = Icons.Filled.Menu,\n                            contentDescription = \"\uba54\ub274\/Menu\"\n                        )\n                    }\n\n                    DropdownMenu(\n                        expanded = expandedLeft,\n                        onDismissRequest = { expandedLeft = false }\n                    ) {\n                        DropdownMenuItem(\n                            text = { Text(\"\uba54\ub2741 \/ Menu1\") },\n                            onClick = { expandedLeft = false }\n                        )\n                        DropdownMenuItem(\n                            text = { Text(\"\uba54\ub2742 \/ Menu2\") },\n                            onClick = { expandedLeft = false }\n                        )\n                    }\n                }\n            },\n\n            \/\/ \uc624\ub978\ucabd \ub354\ubcf4\uae30 \uba54\ub274 \/ More menu on the right\n            actions = {\n                Box {\n                    IconButton(onClick = {\n                        expandedRight = true\n                        expandedLeft = false\n                    }) {\n                        Icon(\n                            imageVector = Icons.Filled.MoreVert,\n                            contentDescription = \"\ub354\ubcf4\uae30\"\n                        )\n                    }\n\n                    DropdownMenu(\n                        expanded = expandedRight,\n                        onDismissRequest = { expandedRight = false }\n                    ) {\n                        DropdownMenuItem(\n                            text = { Text(\"\uc124\uc815 \ubcc0\uacbd \/ Change settings\") },\n                            onClick = { expandedRight = false }\n                        )\n                        DropdownMenuItem(\n                            text = { Text(\"\ub85c\uadf8\uc544\uc6c3 \/ Log out\") },\n                            onClick = { expandedRight = false }\n                        )\n                    }\n                }\n            }\n        )\n    }\n}\n\n\/\/ \ud558\ub2e8 Navigation Bar \ucef4\ud3ec\uc800\ube14 (\ud654\uba74 \uc804\ud658 \ub85c\uc9c1 \ud3ec\ud568)\n\/\/ Bottom Navigation Bar composable (including screen transition logic)\n@Composable\nfun MyBottomNavigationBar(\n    navController: NavHostController,\n    items: List&lt;Screen&gt;\n) {\n    NavigationBar {\n        \/\/ \ud604\uc7ac \ubc31 \uc2a4\ud0dd \ud56d\ubaa9\uc744 State\ub85c \uac00\uc838\uc640 \ud604\uc7ac \ud654\uba74\uc758 Route\ub97c \ud30c\uc545\n        \/\/ Get the current back stack item as State and determine the Route of the current screen\n        val navBackStackEntry by navController.currentBackStackEntryAsState()\n        val currentRoute = navBackStackEntry?.destination?.route\n\n        items.forEach { screen -&gt;\n            NavigationBarItem(\n                icon = { Icon(screen.icon, contentDescription = screen.title) },\n                label = { Text(screen.title) },\n                \/\/ \ud604\uc7ac \ud654\uba74\uc758 route\uc640 \ud0ed \ud56d\ubaa9\uc758 route\uac00 \uac19\uc73c\uba74 \uc120\ud0dd\ub428\n                \/\/ If the route of the current screen and the route of the tab item are the same, it is selected.\n                selected = currentRoute == screen.route,\n                onClick = {\n                    \/\/ \ud074\ub9ad \uc2dc \ud574\ub2f9 \uacbd\ub85c\ub85c \uc774\ub3d9 (\ud654\uba74 \uc804\ud658)\n                    \/\/ Move to the corresponding path when clicked (screen transition)\n                    navController.navigate(screen.route) {\n                        \/\/ \ubc31 \uc2a4\ud0dd\uc5d0\uc11c \uc2dc\uc791 \ud654\uba74\uc744 \uc81c\uc678\ud55c \ubaa8\ub4e0 \ud654\uba74\uc744 \ud31d (\ud0ed \uc804\ud658 \ud45c\uc900 \ud328\ud134)\n                        \/\/ Pop all screens except the start screen from the back stack (standard pattern for tab switching)\n                        popUpTo(navController.graph.startDestinationId) {\n                            saveState = true\n                        }\n                        \/\/ \uac19\uc740 \ud0ed\uc744 \ub2e4\uc2dc \ub20c\ub7ec\ub3c4 \ub2e4\uc2dc \uc0dd\uc131\ud558\uc9c0 \uc54a\uc74c\n                        \/\/ Do not regenerate even if you press the same tab again\n                        launchSingleTop = true\n                        \/\/ \uc774\uc804 \uc0c1\ud0dc \ubcf5\uc6d0\n                        \/\/ restore previous state\n                        restoreState = true\n                    }\n                }\n            )\n        }\n    }\n}\n\n\/\/ NavHost\ub97c \uc0ac\uc6a9\ud558\uc5ec \uacbd\ub85c\uc5d0 \ub530\ub978 \ud654\uba74 \ub9e4\ud551\n\/\/ Mapping screens based on path using NavHost\n@Composable\nfun AppNavigation(\n    navController: NavHostController,\n    modifier: Modifier = Modifier\n) {\n    NavHost(\n        navController = navController,\n        startDestination = Screen.Home.route, \/\/ \uc2dc\uc791 \ud654\uba74 \uc124\uc815 \/ Start screen settings\n        modifier = modifier\n    ) {\n        \/\/ \uacbd\ub85c \uc815\uc758 \ubc0f \ud574\ub2f9 Composable \ud568\uc218 \uc5f0\uacb0 \/ Defining a route and linking its Composable functions\n        composable(Screen.Home.route) { HomeScreen() }\n        composable(Screen.Search.route) { SearchScreen() }\n        composable(Screen.Settings.route) { SettingsScreen() }\n    }\n}\n\n\/\/ \uac01 \uc2a4\ud06c\ub9b0\uc5d0 \ud574\ub2f9\ud558\ub294 \ucef4\ud3ec\uc800\ube14 \ud568\uc218\ub4e4\n\/\/ \uc2a4\ud06c\ub9b0\uc744 \ud30c\uc77c \ubd84\ub9ac \ud558\uc9c0 \uc54a\uc740 \uacbd\uc6b0 \uc774\ub807\uac8c \uc0ac\uc6a9\ud568\n\/\/@Composable\n\/\/fun HomeScreen() {\n\/\/    Text(\"\ud648 \ud654\uba74\uc785\ub2c8\ub2e4.\/Home Screen\")\n\/\/}\n\/\/\n\/\/@Composable\n\/\/fun SearchScreen() {\n\/\/    Text(\"\uac80\uc0c9 \ud654\uba74\uc785\ub2c8\ub2e4.\/Search Screen\")\n\/\/}\n\/\/\n\/\/@Composable\n\/\/fun SettingsScreen() {\n\/\/    Text(\"\uc124\uc815 \ud654\uba74\uc785\ub2c8\ub2e4.\/Settings Screen\")\n\/\/}\n\n@Preview(showBackground = true)\n@Composable\nfun MainScreenPreview() {\n    BottomNavigationBarTheme {\n        MainScreen()\n    }\n}\n\n\/\/ dp\ub97c \uc0ac\uc6a9\ud558\uae30 \uc704\ud574 \uc784\uc2dc\ub85c dp \ud655\uc7a5 \ud568\uc218\ub97c \uc815\uc758 (\uc2e4\uc81c\ub85c\ub294 androidx.compose.ui.unit.dp\ub97c import \ud574\uc57c \ud568)\n\/\/import androidx.compose.ui.unit.dp<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Screens\/HomeScreen.kt<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.freelifemakers.bottomnavigationbar.ui.screens\n\n\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\n\n@Composable\nfun HomeScreen() {\n    Text(\"\ud648 \ud654\uba74 \/ Home Screen.\")\n}<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Screens\/SearchScreen.kt<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.freelifemakers.bottomnavigationbar.ui.screens\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\n\n@Composable\nfun SearchScreen() {\n    Text(text = \"\uac80\uc0c9 \ud654\uba74 \/ Search Screen\")\n}<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Screens\/SettingsScreen.kt<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.freelifemakers.bottomnavigationbar.ui.screens\n\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.material3.Scaffold\nimport androidx.compose.material3.Text\nimport androidx.compose.runtime.Composable\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.tooling.preview.Preview\n\n@Composable\nfun SettingsScreen(modifier: Modifier = Modifier) {\n    Column(modifier = modifier) {\n        Text(text = \"\uc124\uc815 \ud654\uba74 \/ Settings Screen\")\n    }\n\n}\n\n\/\/ \ud504\ub9ac\ubdf0 \uc0ac\uc6a9\n@Preview\n@Composable\nfun SettingScreenPreview(){\n    Scaffold(\n        modifier = Modifier.fillMaxSize()\n    ) { innerPadding -&gt;\n        SettingsScreen(\n            modifier = Modifier.padding(innerPadding)\n        )\n    }\n\n}\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \uc2a4\ud06c\ub9b0\uc0f7\/ScreenShot<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"[Kotlin,Swift]\ud558\ub2e8\ud0ed\uba54\ub274\/BottomTabMenu\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/MSctu4bMl3I?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb \ud558\ub2e8 \ud0ed \uba54\ub274,\ub4dc\ub86d\ub2e4\uc6b4 \uba54\ub274\uc5d0 \ub300\ud55c \uc124\uba85\uc785\ub2c8\ub2e4.Description of the bottom tab menu and drop-down menu. \ud83d\udc49\ud83c\udffb \uc2a4\ud06c\ub9b0 \ud30c\uc77c\uc740 \ub2e4\ub978 \ucf54\ud2c0\ub9b0 \ud30c\uc77c\ub85c \ubd84\ub9ac\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.Screen file is separated into a different Kotlin file. \ud83d\udc49\ud83c\udffb \ub098\uba38\uc9c0 \uc124\uba85\uc740 \ucf54\ub4dc \uc8fc\uc11d\uc744 \ucc38\uc870 \ud558\uc138\uc694Please refer to the code comments for the rest of the explanation. \u2714\ufe0f MainActivity.kt \u2714\ufe0f Screens\/HomeScreen.kt \u2714\ufe0f Screens\/SearchScreen.kt [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,1],"tags":[],"class_list":["post-2779","post","type-post","status-publish","format-standard","hentry","category-kotlin","category-uncategorized","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2779","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=2779"}],"version-history":[{"count":7,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2779\/revisions"}],"predecessor-version":[{"id":2812,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2779\/revisions\/2812"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=2779"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=2779"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=2779"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}