[Jetpack Compose] Navigation Drawer 구현하기
안녕하세요.
오늘은 TopAppBar에서 만든 네비게이션 아이콘에 Navigation Drawer를 연결 해보도록 하겠습니다.
2022.08.08 - [Android/Jetpack] - [Jetpack Compose] TopAppBar(Toolbar) 구현하기
완성된 모습은 아래와 같습니다.
STEP 01 : Drawer 화면 만들기
화면은 아래와 같이 구성해보도록 하겠습니다.
Drawer Header : 프로필 사진, 닉네임
Drawer Body : 화면 이동을 나타내는 네이게이션 아이템
먼저 NavigationDrawer.kt라는 파일을 하나 만듭니다.
해당 파일에 NavigationDrawer 관련 화면을 만들어서 저장할 예정입니다.
전반적인 파일구조는 아래와 같습니다.
@Composable
fun NavigationDrawer(
currentScreen: Screen,
itemClick: (String) -> Unit
) {
val menuList = createDrawerItem(currentScreen)
LazyColumn(
modifier = Modifier
.fillMaxSize()
.background(brush = Brush.verticalGradient(colors = listOf(Color(255, 81, 47),
Color(240, 152, 25)))),
horizontalAlignment = Alignment.CenterHorizontally,
contentPadding = PaddingValues(vertical = 16.dp)
) {
item {
DrawerHeader()
}
items(menuList) { item ->
DrawerBody(item, itemClick)
}
}
}
NavigationDrawer 전체 화면은 LazyColumn을 통해 Vertical 형태로 만들었고,
컬럼이기 때문에 메뉴가 많을때 위아래 스크롤이 가능합니다.
변수로는 NavigationDrawer 시작시 현재 화면을 지정하는 currentScreen과 itemClick 함수를 설정했습니다.
먼저, createDrawerItem()을 통해서 Navigation Drawer Item 메뉴를 만듭니다.
@Composable
private fun createDrawerItem(currentScreen: Screen) = listOf(
NavigationDrawerItem(
image = painterResource(id = ic_baseline_home_24),
isSelected = currentScreen == Screen.Home,
title = "Home"
),
NavigationDrawerItem(
image = painterResource(id = ic_baseline_search_24),
isSelected = currentScreen == Screen.Search,
title = "Search"
),
NavigationDrawerItem(
image = painterResource(id = ic_baseline_pin_drop_24),
isSelected = currentScreen == Screen.Map,
title = "Map"
),
NavigationDrawerItem(
image = painterResource(id = ic_baseline_settings_24),
isSelected = currentScreen == Screen.Settings,
title = "Settings"
),
)
NavigationDrawerItem 객체를 만들어 필요한 변수들을 지정합니다.
아이콘 이미지와 이름 그리고 해당 메뉴가 선택되었는지의 변수를 넣었습니다.
data class NavigationDrawerItem(
val image: Painter,
val isSelected: Boolean,
val title: String
)
DrawerHeader()는 Image와 Text Compasable를 통해서 레이아웃을 구성합니다.
@Composable
private fun DrawerHeader() {
Image(
painter = painterResource(id = ic_baseline_person_24),
contentDescription = "Person",
modifier = Modifier
.padding(top = 16.dp, bottom = 16.dp)
.size(size = 100.dp)
.clip(shape = CircleShape),
colorFilter = ColorFilter.tint(color = Color.White)
)
Text(
text = "안드로이드 개발",
color = Color.White,
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier
.padding(start = 16.dp, bottom = 16.dp)
)
Divider(
color = Color.White,
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
)
}
DrawerBody() Composable에서 NavigationMenuItem를 생성합니다.
@Composable
private fun DrawerBody(
item: NavigationDrawerItem,
itemClick: (String) -> Unit,
) {
NavigationMenuItem(item = item) {
itemClick(item.title)
}
}
@Composable
fun NavigationMenuItem(
item: NavigationDrawerItem,
itemClick: () -> Unit
) {
val texColor = if (item.isSelected) Color.Black else Color.White
val backgroundColor = if (item.isSelected) Color.Yellow else Color.Transparent
Surface(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp),
color = backgroundColor,
shape = MaterialTheme.shapes.small
) {
Row(
modifier = Modifier
.clickable { itemClick() }
.fillMaxWidth()
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
painter = item.image,
contentDescription = null,
tint = texColor
)
Text(
text = item.title,
fontSize = 18.sp,
fontWeight = FontWeight.Medium,
color = texColor,
modifier = Modifier
.padding(start = 16.dp)
)
}
}
}
NavigationMenuItem를 통해서 클릭 이벤트가 있는 메뉴들을 그려줍니다. isSelected를 변수를 통해서 현재 화면에 따라서 아이콘과 텍스트 그리고 배경화면의 색깔을 다르게 지정해 줄 수 있습니다. 현재 화면 메뉴는 배경을 노란색으로 그리고 아이콘과 이름을 횐색으로 지정했습니다.
STEP 02 : Navigation Icon에서 호출하기
@Composable
fun MyApp() {
val context = LocalContext.current
val scaffoldState = rememberScaffoldState()
val scope = rememberCoroutineScope()
Scaffold(
topBar = {
MyTopAppBar(
name = "Toolbar Sample",
scope = scope,
scaffoldState = scaffoldState,
context = context
)
},
scaffoldState = scaffoldState,
drawerContent = {
NavigationDrawer(
currentScreen = Screen.Home
) {
showToast(context, it)
scope.launch {
delay(timeMillis = 200)
scaffoldState.drawerState.close()
}
}
}
) {
}
}
Scaffold 레이아웃을 통해서 Navigation Drawer 화면을 설정할 수 있습니다. rememberScaffoldState()를 변수 scaffoldState에 지정하고, Scaffold 매개변수로 넘겨줍니다. drawerContent에는 이전에 만든 NaviagtionDrawer Composable을 생성하고, currentScreen에 Home 화면을 지정해줍니다. NaviagtionDrawer의 itemClick 식, 토스트 메시지와 drawerState를 close롤 호출하여 Navigation Drawer를 닫아주는 코드를 만듭니다.
@Composable
fun MyTopAppBar(
name: String,
scope: CoroutineScope,
scaffoldState: ScaffoldState,
context: Context,
) {
var shouldShowDialog by remember { mutableStateOf(false) }
var dropdownMenuExpanded by remember { mutableStateOf(false) }
TopAppBar(
title = { Text(text = name) },
contentColor = MaterialTheme.colors.primary,
backgroundColor = Color.Yellow,
navigationIcon = {
IconButton(onClick = {
scope.launch {
scaffoldState.drawerState.open()
}
}) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Menu"
)
}
},
elevation = 12.dp,
actions = {
IconButton(onClick = {
shouldShowDialog = true
}) {
Icon(
imageVector = Icons.Filled.Share,
contentDescription = "Share",
tint = MaterialTheme.colors.primary
)
}
AlertDialogSample(shouldShowDialog = shouldShowDialog) {
shouldShowDialog = false
}
IconButton(onClick = {
dropdownMenuExpanded = true
}) {
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = "MoreVert",
tint = MaterialTheme.colors.primary
)
}
DropDownMenuSample(context, dropdownMenuExpanded) {
dropdownMenuExpanded = false
}
}
)
}
sealed class Screen {
object Home: Screen()
object Search: Screen()
object Map: Screen()
object Settings: Screen()
}
'기리's Android 이야기' 카테고리의 다른 글
미국로또 개인정보 처리방침 (3) | 2023.01.27 |
---|---|
메가세나 개인정보 처리방침 (2) | 2022.10.24 |
[Jetpack Compose] TopAppBar(Toolbar) - 메뉴 클릭 이벤트 (Toast, Alertdialog, Dropdownmenu) (2) | 2022.08.08 |
[Jetpack Compose] TopAppBar(Toolbar) 구현하기 (2) | 2022.08.08 |
[Android/Kotlin] 안드로이드 애드몹(Admob) 전면광고(Interstitial) 넣기(2) (2) | 2022.07.26 |
댓글