CS/Android

Navigation

졔졔311 2024. 12. 16. 11:08
728x90
반응형

Android Navigation : 앱 내에서 화면 전환과 workflow를 관리하기 위한 시스템

Android jetpack의 Navigation Component : 앱의 navigation 구조를 정의, 구현하기 쉽도록 화면 이동, 백 스택 관리, 딥 링크 처리 등의 다양한 기능을 제공하는 도구

 

주요 요소

ㅇ NavHost

화면 전환이 이루어지는 컨테이너.

NavHostFragment나 NavHost Composable을 사용해 Fragment나 Compose 기반으로 설정 가능

ex)

NavHost(navController = navController, startDestination = "home") {
    composable("home") { ... }
    composable("details") { ... }
}

navController는 rememberNavController()를 사용해 생성된 navigation controller이다.

NavHost에서는 navigation controller와 시작 화면(startDestination)을 설정하고, 어떤 화면들이 있는지(home, details) 정의한다.

즉, 앱 실행시 처음 표시될 화면은 "home"이고,

화면의 종류는 "home"과 "details"가 있도록 한 것이다.

 

NavHost로 넘겨진 lambda는 궁극적으로 NavController.createGraph()를 호출해 NavGraph를 리턴한다.

createGraph()를 명시적으로 사용하려면 다음과 같이 구현할 수 있다.

val navGraph by remember(navController) {
  navController.createGraph(startDestination = home)) {
    composable<home> { HomeScreen( /* ... */ ) }
    composable<detail> { DetailScreen( /* ... */ ) }
  }
}
NavHost(navController, navGraph)

 

ㅇ NavGraph

화면 간의 관계와 이동 경로를 정의하는 그래프

XML파일이나 Kotlin DSL로 작성 가능

Destination(화면)끼리의 Action(이동 경로)으로 구성

 

ㅇ NavController

앱의 navigation을 제어하는 핵심 controller

화면 간의 이동을 프로그래밍 방식으로 처리 가능

화면 전환, 백 스택 관리, *딥 링크 처리 등 제공

Jetpack Compose를 사용하며 NavController를 생성하기 위해서는 rememberNavController()를 호출하면 된다.

* rememberNavController()는 내부적으로 remember를 사용해 NavController를 한 번만 생성, recomposition 때마다 동일한 인스턴스를 재사용한다.

composable의 최상단으로 만들어 다른 composable들을 참조할 수 있어야 한다.

 

* Deep Link?
앱 외부에서 특정 화면으로 바로 이동할 수 있는 기능
URI 기반으로 구현

 

ㅇ Destination

앱에서 이동 가능한 개별 화면(Fragment, Composable 등)

ex)

composable("home") {
        HomeScreen(
            onNavigateToDetails = { navController.navigate("details") }
        )
    }

NavHost 내부에서 위와 같이 composable을 통해 "home" 화면을 정의하는 람다 블록을 생성한다.

해당 화면의 UI를 정의하기 위해, 아래와 같이 HomeScreen 함수에 정의할 수 있다.

@Composable
fun HomeScreen(onNavigateToDetails: () -> Unit) {
    Button(onClick = onNavigateToDetails) {
        Text("Go to Details")
    }
}

 

HomeScreen()은 "details" 화면으로 전환시켜주는 버튼을 가지고 있지만, navigate()를 스스로 호출하지는 않고, 버튼이 onNavigateToDetails를 호출한다.

navigation graph에 HomeScreen이 추가될 경우 onNavigateToDetails라는 매개변수(콜백)에 "navigate(route=details)"를 호출하는 lambda( = {navController.navigate("details")})를 전달한다.


실제로 사용해보기

더보기
package com.example.composetutorial

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.compose.rememberNavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApp {
                AppNavigation() // 네비게이션 그래프 렌더링
            }
        }
    }
}

@Composable
fun MyApp(content: @Composable () -> Unit) {
    MaterialTheme { // Material3 테마 설정
        content()
    }
}

@Composable
fun AppNavigation() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = "home") {
        composable("home") {
            HomeScreen(
                onNavigateToDetails = { navController.navigate("details") }
            )
        }
        composable("details") {
            DetailsScreen()
        }
    }
}

@Composable
fun HomeScreen(onNavigateToDetails: () -> Unit) {
    Button(onClick = onNavigateToDetails) {
        Text("Go to Details")
    }
}

@Composable
fun DetailsScreen() {
    Text("This is the Details Screen")
}

@Preview(showBackground = true)
@Composable
fun PreviewApp() {
    MyApp {
        AppNavigation()
    }
}

home과 details라는 두 개의 화면을 만들고, 시작 화면을 home으로 설정하였다.

home에서는 button을 누르면 details 화면으로 이동하게 되고,

details 화면에서는 "This is the Details Screen"이라는 문구만 뜨게 된다.

 

실행 화면

시작했을 때의 이미지("home"화면)

 

버튼을 클릭한 경우의 화면("Details"화면)

728x90
반응형

'CS > Android' 카테고리의 다른 글

Coroutine (1)  (0) 2024.12.17
공통 객체 이용하기 - CompositionLocal  (0) 2024.12.17
Composable & Preview  (0) 2024.12.13
Ktlint vs Detekt vs Android Lint  (1) 2024.12.13
DATA BINDING  (0) 2024.12.13