Grusie 안드로이드 개발 기술 블로그

[Android] JetPack:Compose 네비게이션(navigation) - 1 본문

안드로이드 개발/라이브러리

[Android] JetPack:Compose 네비게이션(navigation) - 1

grusie 2024. 3. 6. 17:37
728x90
반응형
SMALL

JetPack:Compose를 사용해 개발을 하던 도중, 화면 이동을 위해서 네비게이션 라이브러리가 사용되는 것을 알았다.

예시를 보고 구현을 하였으나, 완벽히 이해를 한 것이 아니어서 공식문서를 보며 정리 해두려고 한다.

 

이론적인 부분보다, 구현 부분이 많아 예시코드를 분리하지 않고 코드랩을 따라가면서 정리할 예정이다.

 

의존성

dependencies {
    val nav_version = "2.7.7"

    implementation("androidx.navigation:navigation-compose:$nav_version")
}

 

Navigation의 주요 구성요소

  • NavController : 대상(즉, 앱의 화면) 간 이동을 담당한다.
  • NavGraph : 이동할 컴포저블 대상을 매핑한다.
  • NavHost : NavGraph의 현재 대상을 표시하는 컨테이너 역할을 하는 컴포저블이다.
더보기

탐색에서의 경로

- Compose 앱에서 탐색의 기본 개념 중 하나이며, 문자열로 나타낸다.

- URL의 개념과 유사하며, 다른 대상에 매핑되어 고유한 식별자 역할을 하는 문자열이다.

- Kotlin의 enum클래스를 사용하여 앱의 경로를 지정할 수 있다.(Sealed Class나 인터페이스 등도 가능)

 

enum class Screen {
    First,
    Second,
    Third
}

enum 클래스에 각 화면에 해당하는 명칭을 추가한다.

 

NavHost 추가

NavHost 구조
이미지 출처 : https://developer.android.com/codelabs/basic-android-kotlin-compose-navigation?hl=ko#3

 

NavHost는 지정된 경로를 기반으로 다른 컴포저블 대상을 표시하는 컴포저블이다.

 

주목할 만한 매개변수

  • navController : NavHostController 클래스의 인스턴스이다. navigate() 메서드를 호출하여 다른 대상으로 이동하는 등의 방식으로 화면 간에 이동하는데 이 객체를 사용할 수 있다. Composable함수에서 rememberNavController()를 호출하여 NavHostController를 가져올 수 있다.
  • startDestination : 앱에서 NavHost를 처음 표시할 때 기본적으로 표시되는 대상을 정의하는 문자열 경로이다.
더보기

참고 : NavHostController는 NavHost 컴포저블과 함께 사용할 추가 기능을 제공하는 NavController 클래스의 서브클래스이다.

 

NavHost()함수를 생성한 뒤, 원하는 스크린에 추가한다.

import androidx.navigation.compose.NavHost

Scaffold(
    ...
) { innerPadding ->
    val uiState by viewModel.uiState.collectAsState()

    NavHost()
}

 

import androidx.compose.foundation.layout.padding

NavHost(
    navController = navController,
    startDestination = CupcakeScreen.Start.name,
    modifier = Modifier.padding(innerPadding)
) {

}

 

NavHost 에서 경로 처리

다른 컴포저블과 마찬가지로 NavHost는 콘텐츠의 함수 유형을 사용한다.

composable과 주소를 통한 경로 처리
이미지 출처 : https://developer.android.com/codelabs/basic-android-kotlin-compose-navigation?hl=ko#3

 

NavHost의 콘텐츠 함수 내에서 composable()함수를 호출한다.

composable()함수의 필수 매개변수

  • route : 경로 이름에 해당하는 문자열이다. 모든 고유 문자열을 사용할 수 있다. Screen enum의 상수 이름 속성을 사용한다.
  • content : 여기에서 특정 경로에 표시할 컴포저블을 호출할 수 있다.
더보기

참고: composable() 함수는 NavGraphBuilder의 확장 함수이다.

NavHost(
    navController = navController,
    startDestination = Screen.First.name,
    modifier = Modifier.padding(it)
) {
    composable(route = Screen.First.name) {
    }
}

1. composable() 함수를 사용하여 route에 Screen.First.name을 전달한다.

 

NavHost(
    navController = navController,
    startDestination = Screen.First.name,
    modifier = Modifier.padding(it)
) {
    composable(route = Screen.First.name) {
        FirstScreen(
        	...
        )
    }
}

2. composable 함수의 후행 람다(마지막 매개변수) 내에서 FirstScreen을 추가한다.

 

composable(route = Screen.Second.name) {
    SecondScreen(
    	...
    )
}

composable(route = Screen.Third.name) {
    ThirdScreen(
    	...
    )
}

3. 마찬가지로 Second와 Third 스크린도 추가한다.

 

경로 간 이동

rememberNavController()호출의 navController 속성인 NavHostController는 경로 간 이동을 담당한다.

경로 간 이동을 위해 navController의 navigate()함수를 이용한다.

composable(route = Screen.First.name) {
    FirstScreen(onNextBtnClicked = { navController.navigate(Screen.Second.name) })
}

...
...

@Composable
fun FirstScreen(onNextBtnClicked: () -> Unit) {
    Button(onClick = { onNextBtnClicked() }) {
        Text(text = "secondScreen")
    }
}

FirstScreen에서 Button 클릭 시 SecondScreen으로 이동하는 코드이다.

 

navController를 그대로 넘기지 않고, 이를 참조해야 하는 모든 컴포저블이 액세스 할 수 있는 곳에 선언해두고, 사용하도록 구현하는게 상태 호이스팅 원칙을 준수하는 것이다.

 

composable(route = Screen.Third.name) {
    ThirdScreen(onBackBtnClicked = {
        navController.popBackStack(
            Screen.First.name,
            false
        )
    })
}

시작 화면으로 돌아가기

popBackStack() 

- route: 다시 돌아갈 대상의 경로를 나타내는 문자열이다.

- inclusive : 불리언 값으로, true이면 지정된 경로를 삭제한다. false이면 popBackStack()은 시작 대상 위의 모든 대상을 삭제하여(시작 대상은 제외) 시작 대상을 사용자에게 표시하는 최상단 화면으로 둔다.

 

다른 앱으로 이동

다른 앱으로 이동 할 때에는 ShareSheet라는 Android 운영체제에서 제공하는 UI를 사용할 수 있다. 시스템 UI는 navController를 사용하지 않고 Intent를 사용한다.

Intent에서의 ACTION_SEND 액션을 사용한다.

 

인텐트를 설정하는 기본 프로세스는 다음과 같다.

  1. 인텐트 객체를 만들고 ACTION_SEND 등의 인텐트를 지정한다.
  2. 인텐트와 함께 전송되는 추가 데이터의 유형을 지정한다. 간단한 텍스트에는 "text/plain"을 사용할 수 있지만 "image/*" 또는 "video/*"와 같은 다른 유형도 사용할 수 있다.
  3. putExtra() 메서드를 호출하는 방식으로 공유할 텍스트 또는 이미지와 같은 추가 데이터를 인텐트에 전달한다. 이 인텐트는 두 가지 추가 항목인 EXTRA_SUBJECT과 EXTRA_TEXT를 사용한다.
  4. 컨텍스트의 startActivity() 메서드를 호출하여 인텐트에서 생성된 활동을 전달한다.
private fun shareData(context: Context, text1: String, text2: String) {
    val intent = Intent(Intent.ACTION_SEND).apply {
        type = "text/plain"
        putExtra(Intent.EXTRA_SUBJECT, text1)
        putExtra(Intent.EXTRA_TEXT, text2)
    }

    context.startActivity(
        Intent.createChooser(
            intent,
            context.getString(R.string.app_name)
        )
    )
}

private으로 ShareData()함수를 만들고,

intent를 활용하여, "text/plain" 형태의 데이터를 전달하여, Chooser를 실행시켜 전달 할 수 있도록 한다.

composable(route = Screen.Third.name) {
    val context = LocalContext.current
    ThirdScreen(onBackBtnClicked = {
        navController.popBackStack(
            Screen.First.name,
            false
        )
    },
        onSharedBtnClicked = {text1, text2 ->
            shareData(context, text1, text2)
        }
    )
}

 

shareData를 사용하기 위해 ThirdScreen에 람다로 넘겨준 모습이다.

Button(onClick = { onSharedBtnClicked("text1", "text2") }) {
    Text(text = "sharedButton")
}

사용법은 이렇게, 버튼을 클릭 시, onSharedBtnClicked() 함수에 매개변수 두 개를 넣고, 실행시킨다.

네비게이션을 통한 이동 처리
실제 작동 화면

참고

https://developer.android.com/codelabs/basic-android-kotlin-compose-navigation?hl=ko#0

 

Compose를 사용하여 화면 간 이동  |  Android Developers

Cupcake 앱에 Navigation 구성요소를 추가하여 앱의 흐름을 구성하고 여러 화면 간에 데이터를 탐색하고 전달합니다.

developer.android.com

https://developer.android.com/jetpack/compose/navigation?hl=ko

 

Compose를 사용한 탐색  |  Jetpack Compose  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. Compose를 사용한 탐색 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Navigation 구성요소는 Jetpack Compose

developer.android.com

후기

이렇게 JetPack:Compose 내에서 JetPack:Navigation라이브러리를 활용하여 화면 이동 하는 법에 대해서 알아보았고, 다음 글에서 화면 이동 시 데이터 전송을 하는 법에 대해서 알아보자.

반응형
LIST