일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Navigation
- scroll
- Compose
- livedata
- CustomScrollView
- LifeCycle
- Button
- 안드로이드
- Flutter
- Dialog
- 계측
- TEST
- tabbar
- drift
- appbar
- viewmodel
- 앱바
- textfield
- data
- textview
- android
- intent
- Kotlin
- ScrollView
- 앱
- activity
- binding
- 테스트
- DART
- Coroutines
- Today
- Total
Study Record
[Android] Compose 화면 간 이동(Navigation) 본문
😶 앱에서 대상 경로 정의
Compose 에서 한 화면에서 다른 화면으로 넘어가는 탐색의 기본 개념 중 하나는 경로이다. 경로는 URL 개념과 유사하게 다른 URL 이 웹사이트의 다른 페이지에 매핑되는 것처럼 경로는 대상에 매핑되어 고유한 식별자 역할을 하는 문자열이다. 대상은 일반적으로 사용자에게 표시되는 항목에 상응하는 단일 컴포저블리거나 그 컴포저블 그룹을 뜻한다.
😶 Navigation 구성요소
Naviagtion 구성요소는 세가지로 나뉜다.
NavController
대상(앱의 화면) 간 이동을 담당한다.
NavGraph
이동할 컴포저블 대상을 매핑한다.
NavHost
NavGraph 의 현재 대상을 표시하는 컨테이너 역할을 하는 컴포저블이다.
😶 화면 이동 방법 (NavHost, NavController)
NavHost 는 지정된 경로를 기반으로 다른 컴포저블 대상을 표시하는 컴포저블이다. NavHost 는 다음과 같이 사용할 수 있다. navController 는 NavHostController 클래스의 인스턴스로 navigate() 메서드를 호출하여 다른 대상으로 이동하는 등의 방식으로 화면 간에 이동하는 데 이 객체를 사용할 수 있다. startDestination 은 앱에서 NavHost 를 처음 표시할 때 기본적으로 표시되는 대상을 정의하는 문자열 경로이다.
NavHost(
navController,
startDestination,
modifier
){
content
}
예시를 들 화면은 다음과 같다고 하자. 각 NEXT 버튼을 누르면 다음 화면으로 넘어가고 BACK 버튼을 누르면 처음 화면으로 돌아간다.
전체 코드는 다음과 같다.
enum class NavigationTestScreen {
ONE, TWO, THREE, FOUR
}
@Composable
fun NavigationTestApp() {
val navController = rememberNavController()
Scaffold { innerPadding ->
NavHost(
navController = navController,
startDestination = NavigationTestScreen.ONE.name,
modifier = Modifier.padding(innerPadding)
) {
composable(route = NavigationTestScreen.ONE.name) {
TestScreen(
screenTest = "ONE SCREEN",
isBack = false,
onNextButtonClicked = { navController.navigate(NavigationTestScreen.TWO.name) },
)
}
composable(route = NavigationTestScreen.TWO.name) {
TestScreen(
screenTest = "TWO SCREEN",
onNextButtonClicked = { navController.navigate(NavigationTestScreen.THREE.name) },
onBackButtonClicked = {
navController.popBackStack(
NavigationTestScreen.ONE.name,
inclusive = false
)
}
)
}
composable(route = NavigationTestScreen.THREE.name) {
TestScreen(
screenTest = "THREE SCREEN",
onNextButtonClicked = { navController.navigate(NavigationTestScreen.FOUR.name) },
onBackButtonClicked = {
navController.popBackStack(
NavigationTestScreen.ONE.name,
inclusive = false
)
}
)
}
composable(route = NavigationTestScreen.FOUR.name) {
TestScreen(
screenTest = "FOUR SCREEN",
isNext = false,
onBackButtonClicked = {
navController.popBackStack(
NavigationTestScreen.ONE.name,
inclusive = true
)
}
)
}
}
}
}
@Composable
fun TestScreen(
screenTest: String,
isBack: Boolean = true,
isNext: Boolean = true,
onBackButtonClicked: () -> Unit = {},
onNextButtonClicked: () -> Unit = {},
modifier: Modifier = Modifier
) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
.padding(20.dp)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = screenTest, color = Color.White)
Spacer(modifier = Modifier.height(12.dp))
if (isBack) {
OutlinedButton(onClick = onBackButtonClicked) {
Text(text = "BACK")
}
}
Spacer(modifier = Modifier.height(12.dp))
if (isNext) {
OutlinedButton(onClick = onNextButtonClicked) {
Text(text = "NEXT")
}
}
}
}
NavHost 의 content 함수 내에서 composable() 함수를 호출할 수 있다. 이 함수의 route 변수는 경로 이름에 해당하는 문자열로 모든 고유 문자열을 사용할 수 있다.
enum class NavigationTestScreen {
ONE, TWO, THREE, FOUR
}
NavHost(
navController = navController,
startDestination = NavigationTestScreen.ONE.name,
modifier = Modifier.padding(innerPadding)
) {
composable(route = NavigationTestScreen.ONE.name) {
TestScreen(
screenTest = "ONE SCREEN",
isBack = false,
onNextButtonClicked = { navController.navigate(NavigationTestScreen.TWO.name) },
)
}
...
)
NavController 는 rememberNavController() 로 정의할 수 있다. 이 navController 로 다음 화면(composable())으로 넘어갈 수 있는데 예시 코드에서는 navigate(), popBackStack() 메서드가 사용되었다.
val navController = rememberNavController()
Scaffold { innerPadding ->
NavHost(
navController = navController,
startDestination = NavigationTestScreen.ONE.name,
modifier = Modifier.padding(innerPadding)
) {
...
composable(route = NavigationTestScreen.TWO.name) {
TestScreen(
screenTest = "TWO SCREEN",
onNextButtonClicked = { navController.navigate(NavigationTestScreen.THREE.name) },
onBackButtonClicked = {
navController.popBackStack(
NavigationTestScreen.ONE.name,
inclusive = false
)
}
)
}
...
}
}
navgate() 에 원하는 고유 경로 이름을 변수로 넣어주면 그 화면으로 이동한다. popBackStack() 은 첫번째 매개변수로 원하는 경로로 이동한다. 두번째 매개변수 inclusive 가 true 이면 첫번째 매개변수의 화면까지 종료하고 false 이면 첫번째 매개변수는 종료하지 않는다.
😶 앱바 뒤로가기
enum class NavigationTestScreen {
ONE, TWO, THREE, FOUR
}
@Composable
fun NavigationTestApp() {
val navController = rememberNavController()
val backStackEntry by navController.currentBackStackEntryAsState()
Scaffold(
topBar = {
TestAppBar(
canNavigateBack = navController.previousBackStackEntry != null,
navigateUp = { navController.navigateUp() },
currentScreen = backStackEntry?.destination?.route ?: NavigationTestScreen.ONE.name
)
}
) { innerPadding ->
/* ... */
}
}
@Composable
fun TestAppBar(
canNavigateBack: Boolean,
navigateUp: () -> Unit,
currentScreen: String,
modifier: Modifier = Modifier
) {
TopAppBar(
title = { Text(currentScreen) },
colors = TopAppBarDefaults.mediumTopAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer
),
modifier = modifier,
navigationIcon = {
if (canNavigateBack) {
IconButton(onClick = navigateUp) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(R.string.back_button)
)
}
}
}
)
}
'안드로이드 > compose' 카테고리의 다른 글
[Android] Compose 앱바와 Navigation 연결하기 (0) | 2023.11.17 |
---|---|
[Android] Compose 다이얼로그 (0) | 2023.09.13 |
[Android] Compose 단위 테스트 (0) | 2023.09.13 |
[Android] Compose ViewModel (0) | 2023.09.13 |
[Android] Compose 애니메이션 효과 (0) | 2023.09.06 |