์ด๋ฒ ํฌ์คํ ์์๋ compose ui๋ก bottom navigation์ ๋ง๋๋ ์์ ๋ฅผ ์ ๋ฆฌํด ๋ณผ ๊ฒ์ด๋ค.
์ด์ ํฌ์คํ
https://rkdrkd-history.tistory.com/46
compose๋ก bottom navigation์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ง๋ง, ํ์๋ navigation compose์์ ์ ๊ณต๋๋ BottomNavigation์ ์ฌ์ฉํด ๋ง๋ค์ด ๋ณด๊ฒ ๋ค.
1. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
app ๋จ์์ gradle์ ๋ค์๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํ๋ค.
implementation "androidx.navigation:navigation-compose:2.5.3"
2. ๋ณธ๊ฒฉ์ ์ผ๋ก ๊ตฌํํ๊ธฐ
์ผ๋จ ํ์๋ 3๊ฐ์ ํญ(๊ฒ์, ํ, ํ๋กํ)์ผ๋ก ๊ตฌ์ฑ๋ bottom navigation์ ๋ง๋ค์ด ๋ณด๊ฒ ๋ค.
1. ํ๋ฉด์ ๋ด์๋๋ ํด๋์ค
๊ฐ์ฅ ๋จผ์ ํด์ผ ํ ๊ฒ์
bottom navigation์ ๋ค์ด๊ฐ screen(ํ๋ฉด)์ ๋ด์๋๋ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
sealed class BottomNavItem(
val icon: Int, val screenRoute: String
) {
object Search: BottomNavItem(R.drawable.search_icon, Screen.SearchScreen.route)
object Home: BottomNavItem(R.drawable.home_icon, Screen.HomeScreen.route)
object Profile: BottomNavItem(R.drawable.profile_icon, Screen.ProfileScreen.route)
}
sealed class๋ฅผ ์ฐ๋ ์ด์ ?
- kotlin์ sealed class๋ ์ถ์ ํด๋์ค๋ก ์์๋ฐ๋ ์์ ํด๋์ค์ ์ข ๋ฅ๋ฅผ ์ ํํ๋ ์ญํ ์ ํ๊ธฐ ๋๋ฌธ์ ์ปดํ์ผ๋ฌ์์ sealed class์ ์์ ํด๋์ค๊ฐ ๋ช์ด๋ ๋๋์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ๋์ค์ ์ธ ์ฝ๋์์ when๋ฌธ์ ์ฌ์ฉํ ๋, else๋ฅผ ๋ฃ์ง ์์๋ ๋๋ ์ฅ์ ์ด ์๋ค.
์์ ํด๋์ค์ ๊ตฌ์ฑ ์์๋ก๋ ์์ด์ฝ, route๊ฐ ์๋ค(title์ ์ถ๊ฐํ๊ณ ์ถ์ผ๋ฉด ๋ถ๋ชจ ํด๋์ค์ title ํ๋ผ๋ฏธํฐ๋ฅผ ๋ง๋ค์ด์ ๊ตฌํํ๋ฉด ๋๋ค).
์ฌ๊ธฐ์ route๋ ํ์ฌ ์คํฌ๋ฆฐ์ ์ฃผ์๋ผ๊ณ ์๊ฐํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
(route๋ ์ถํ์ ๊ตฌํํ ๋ ์์ฃผ ์ฐ์ด๊ธฐ ๋๋ฌธ์ ๋ณ์๋ก ๋ง๋ค์ด์ ์ ์ฅํด๋๋๊ฒ ์ข์ ๋ฏํ๋ค.)
์๋ก ์ด ๊ธธ์์ง๋ง ์ผ๋จ ํ์๋ 3๊ฐ์ screen์ bottom navigation์ ๋ง๋ค ๊ฒ์ด๊ธฐ ๋๋ฌธ์ 3๊ฐ์ ์์ ํด๋์ค(object class)๋ค์ ๋ง๋ค์ด์ฃผ์๋ค.
2. Screen ๊ฐ์ ์ด๋์ ์ํ Navigation๊ตฌํํ๊ธฐ
@Composable
fun NavigationGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = BottomNavItem.Home.screenRoute
) {
composable(BottomNavItem.Search.screenRoute) {
SearchScreen()
}
composable(BottomNavItem.Home.screenRoute) {
HomeScreen()
}
composable(BottomNavItem.Profile.screenRoute) {
ProfileScreen()
}
}
}
navigation์ compose์์ ํ๋ฉด์ ์ด๋ํ๊ธฐ ์ํ ์ฅ์น๋ผ ํ ์ ์๋ค.
NavHost์์ startDestination์ ์ฑ์ด ์์๋์์ ๋ ์ฒ์์ผ๋ก ๋์ค๋ screen์ด๋ผ๊ณ ๋ณด๋ฉด ๋๊ฒ ๋ค.
NavHost์์ ํ์ฌ route์ ๋ฐ๋ผ์ ํ์ด๋์ฌ(?) screen๋ค์ ๊ด๋ฆฌํ๋ค.(composable() ์์ screen ํจ์๋ ํ์๊ฐ ๋ง๋ composable ํจ์์ด๊ธฐ์ ์ด ๊ธ์ ๋ณด์๋ ๋ถ๋ค์ ์ง์ ๋ง๋ค์ด๋ณด์๊ธธ ๋ฐ๋๋ค.)
3. ์ง์ง ๋ณธ๊ฒฉ์ ์ผ๋ก ๊ตฌํํ๊ธฐ(?)
์ด์ ์ง์ง๋ก bottom navigation์ ๊ตฌํํด ๋ณด์.
@Composable
fun BottomNavigationView(navController: NavController) {
val items = listOf(
BottomNavItem.Search,
BottomNavItem.Home,
BottomNavItem.Profile
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
BottomNavigation(
backgroundColor = Color.White,
contentColor = Color.Black
) {
items.forEach { item ->
BottomNavigationItem(
icon = {
Icon(
painter = painterResource(id = item.icon),
contentDescription = null,
modifier = Modifier.size(30.dp)
)
},
selected = currentRoute == item.screenRoute,
onClick = {
navController.navigate(item.screenRoute) {
navController.graph.startDestinationRoute?.let {
popUpTo(it) { saveState = true }
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
๋์ถฉ ์ฝ๋์ ์ญํ ์ ์ค๋ช ํ์๋ฉด
- BottomNavigation ํ๋ผ๋ฏธํฐ: backgroundColor(๋ฐฐ๊ฒฝ์), contentColor(์์ดํ ์ด ํด๋ฆญ๋์์ ๋์ ์)
- items: ํ์ฌ ์คํฌ๋ฆฐ๋ค์ ๋ชจ์๋์ ๋ฆฌ์คํธ๋ก, forEach ๋ฌธ์์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ง๋ ๋ณ์์ด๋ค.
(ํ์์ ๊ฒฝ์ฐ์๋ screen๋ง๋ค ๊ตฌํํ ๋ก์ง์ด ๊ฐ๊ธฐ ๋๋ฌธ์ list๋ก ๋ง๋ค์ด ๊ตฌํํ์ง๋ง, ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ์๋ BottomNavigationItem์ ๋ฐ๋ก๋ฐ๋ก ๋ง๋ค์ด ๊ตฌํํด ๋ณด์) - icon: bottom navigation์ ์์ด์ฝ์ด ์์นํ๋ ๊ณณ์ด๋ค.
- selected: ํด๋น ์์ดํ ์ด ํด๋ฆญ๋์์ ๋, ํด๋น screen์ route๋ฅผ currentRoute๋ก ์ค์ ํ๋ค.
- onClick: ํด๋น ์์ดํ
์ด ํด๋ฆญ๋์์ ๋์ ๋ก์ง์ ์์ฑํ๋ ๊ณณ์ด๋ค.
onclick ์์๋ navigate(route)๋ฅผ ์ฌ์ฉํด ํด๋น ์คํฌ๋ฆฐ์ ๋งจ ์๋ก ์ฌ๋ ค์(popUpTo()) ์ฑ์ ํ๋ฉด์ ๋ณด์ด๊ฒ ๋ง๋ค์๋ค.
4. ๋ง๋ ๊ฑฐ ๋ถ์ด๊ธฐ(?)
์ด์ ๋ง๋ bottom navigation์ activity์ ๋ถ์ฌ๋ณด๊ฒ ๋ค.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SetBottomNav()
}
}
}
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SetBottomNav() {
val navController = rememberNavController()
Scaffold(
modifier = Modifier.fillMaxSize().systemBarsPadding(),
bottomBar = {
BottomNavigationView(navController = navController)
}
) {
NavigationGraph(navController = navController)
}
}
Scaffold์ bottomBar ํ๋ง๋ฆฌํฐ๋ฅผ ์ฌ์ฉํด ๊ตฌํํ๋ค.
๋ํ Scaffold ๋ณธ๋ฌธ์ ์๊น ์ ์ํ navigation์ ๋ฌ์๋ค(?)
5. ๊ฒฐ๊ณผ
์ ๋ฆฌ
- xml bottom navigation view์ ์ต์ํด์ ธ ์๋ ํ์์๊ฒ๋ compose๋ก ๊ตฌํํ๋ ๊ฒ์ ํฐ ๊ณผ์ ์๋ค(ใ ใ ).
- xml ๋์๋ ๋ค๋ฅธ ๊ฒ navigation์ ์ด์ฉํด bottom navigation์ ๊ตฌํํด์ผ ํ๋ค๋ ๊ฒ์ด ์๋นํ ํ๋ค์์ง๋ง, ์ญ์ ์์ฑ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด์ ๋ฟ๋ฏํ ๊ฐ์ ์ ์ฐธ์ ์๊ฐ(?) ์์๋ค.
๋ค์ ํฌ์คํ ์์๋ ํ์๊ฐ search screen, home screen์ ๊ตฌํ๋์ด ์๋ compose๋ก grid recyclerview ๋ง๋ค๊ธฐ๋ฅผ ์ฌ๋ฆด ์์ (?)์ด๋ค.
'๐ฑ| Android > ๐ | Jetpack' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android, Kotlin] compose์์ api ํต์ ํ๊ธฐ (2) | 2023.08.03 |
---|---|
[Android, Kotlin] Compose UI ์ ๋ฆฌ(7) (2) | 2023.04.16 |
[Android, Kotlin] Android Activity์ lifeCycle ์ ๋ฆฌ (0) | 2023.03.17 |
[Android, Kotlin] Compose UI ์ ๋ฆฌ(5) (0) | 2023.03.13 |
[Android, Kotlin] Compose UI ์ ๋ฆฌ(4) (0) | 2022.12.05 |