[안드로이드 스튜디오 코틀린] Jetpack Compose Bottom Navigation 으로 바텀 바 만들기( + FontAwecome)
로그인 화면에서 버튼을 누르면 메인화면으로 진입하고 ,
메인화면에는 4개의 바텀메뉴가 있고 Home화면이 시작인 화면을 만들어보겠습니다.
FontAwesome을 사용하려면
https://github.com/Gurupreet/FontAwesomeCompose
아래와 같이 추가해주세요
repositories {
maven { url 'https://jitpack.io' }
}
// App build.gradle
dependencies {
implementation 'com.github.Gurupreet:FontAwesomeCompose:1.0.0'
}
그리고, navigation 사용을 위한 implementation 추가도 해줍니다.
implementation 'androidx.navigation:navigation-runtime-ktx:2.7.7'
implementation 'androidx.navigation:navigation-compose:2.7.7'
NavigationData Model 사용을 위한 data class를 만들어주세요.
data class NavigationData(
val title: String,
val icon: FaIconType
)
그리고 ui ->에 screen 폴더를 만들어줍니다.
MainScreen.kt, LoginScreen.kt, BottomMenuScreen.kt
를 만들고
ui -> screen -> bottom 폴더를 만들어서
HomeScreen.kt, SearchScreen.kt, ListScreen.kt, MyScreen.kt를 만들어줍니다.
이렇게 폴더를 나눠보았습니다.
HomeScreen.kt, SearchScreen.kt, ListScreen.kt, MyScreen.kt 내용은 간단하게
Text로만 화면을 보여주겠습니다.
@Composable
fun HomeScreen() {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxSize()
) {
Text("홈 화면")
}
}
네 개 다 이렇게 글자만 바꿔서 만들어주세요.
BottomMenuScreen.kt는
package com.example.jetpackcomposenavigationbarexam.ui.screen
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.example.jetpackcomposenavigationbarexam.data.NavigationData
import com.example.jetpackcomposenavigationbarexam.ui.screen.bottom.HomeScreen
import com.example.jetpackcomposenavigationbarexam.ui.screen.bottom.ListScreen
import com.example.jetpackcomposenavigationbarexam.ui.screen.bottom.MyScreen
import com.example.jetpackcomposenavigationbarexam.ui.screen.bottom.SearchScreen
import com.guru.fontawesomecomposelib.FaIcon
import com.guru.fontawesomecomposelib.FaIcons
@Composable
fun BottomMenuScreen(navController: NavController) {
val navMenus = listOf(
NavigationData("홈", FaIcons.Home),
NavigationData("검색", FaIcons.Search),
NavigationData("목록", FaIcons.List),
NavigationData("My", FaIcons.User)
)
var selectedItem by remember { mutableStateOf(0) }
Scaffold(
bottomBar = {
BottomAppBar {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround
) {
navMenus.forEachIndexed { index, menu ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(8.dp)
.clickable { selectedItem = index }
) {
FaIcon(
faIcon = menu.icon,
tint = if (selectedItem == index) Color.Black else Color.Gray,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.padding(2.dp))
Text(
text = menu.title,
color = if (selectedItem == index) Color.Black else Color.Gray
)
}
}
}
}
}
) { paddingValues ->
Box(
modifier = Modifier.padding(paddingValues),
contentAlignment = Alignment.Center
) {
when (selectedItem) {
0 -> HomeScreen()
1 -> SearchScreen()
2 -> ListScreen()
3 -> MyScreen()
}
}
}
}
data class로 만든 NavigationData를 이용해서 생성하고, forEachIndexed를 이용해 menu를 꺼내옵니다.
그리고 index를 통해 클릭 이벤트를 주었습니다.
MainScreen.kt는 사실 BottomNavigation 전체를 감싸고 있는 화면이라
import androidx.compose.runtime.Composable
import androidx.navigation.NavController
@Composable
fun MainScreen(navController: NavController) {
BottomMenuScreen(navController = navController)
}
이렇게 간단하게 만들어서 연결해주었습니다.
LoginScreen.kt는
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import com.example.jetpackcomposenavigationbarexam.ui.theme.JetpackComposeNavigationBarExamTheme
@Composable
fun LoginScreen(navController: NavController) {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.weight(1f))
Text(text = "로그인 화면")
Spacer(modifier = Modifier.weight(1f))
Button(
onClick = { navController.navigate("home")},
modifier = Modifier.padding(bottom = 40.dp)
) {
Text(text = "로그인 버튼입니다.")
}
}
}
}
@Preview(showBackground = true)
@Composable
fun LoginScreenPreview() {
val navController = rememberNavController()
JetpackComposeNavigationBarExamTheme {
LoginScreen(navController = navController)
}
}
이렇게 Text와 버튼이 하나 있는 화면으로 구성하였습니다.
이제 MainActivity.kt
package com.example.jetpackcomposenavigationbarexam
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.example.jetpackcomposenavigationbarexam.ui.screen.LoginScreen
import com.example.jetpackcomposenavigationbarexam.ui.screen.MainScreen
import com.example.jetpackcomposenavigationbarexam.ui.theme.JetpackComposeNavigationBarExamTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetpackComposeNavigationBarExamTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
MyApp()
}
}
}
}
}
@Composable
fun MyApp() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "login"
) {
composable("login") { LoginScreen(navController = navController) }
composable("home") { MainScreen(navController = navController) }
}
}
@Preview(showBackground = true)
@Composable
fun MainScreenPreview() {
JetpackComposeNavigationBarExamTheme {
MyApp()
}
}
NavHost를 통해 startDestination을 주고,
LoginScreen.kt에서
onClick = {navController.navigate("home")}
을 호출하면 MainScreen이 나타나는걸 볼 수 있습니다.
총 코드
https://github.com/songmik/JetpackComposeNavigationBarExam