안드로이드에서 화면을 전환하는 방법은 여러 가지가 있습니다.
쉽게 생각하는 방법은 액티비티를 여러 개 사용하여 해당 액티비티끼리의 이동으로 화면의 전환을 보여주는 방법이 있습니다. 이경우 Intent를 통하여 이동작을 진행하는데 화면의 전환할 때 공유하는 View가 필요할 때가 있습니다. 이때 데이터를 보내준다면 공유를 할 수 있으나 화면전환 시의 부자연스럽고 해당 동작을 구현해야 된다는 단점이 있습니다. 이때 Fragment를 사용한다면 액티비티에서 해당 화면만 전환하게 되니 좀 더 자연스럽고 손쉽게 해당 화면을 구현할 수 있습니다.
Fragment의 연결하는 방법은 이러한 단점을 해결할 수 있지만 코드로 구현돼 있고 어떻게 진행이 되는지 한눈에 들어오지는 않습니다. 이때 Navigation을 사용한다면 이러한 점을 해결할 수 있습니다. Navigation은 Fragment의 탐색과 이동을 관리를 도와주는 Android JetPack 라이브러리입니다. 이동시 애니메이션을 줄 수 있고 이동시 트렌젝션이나 동작으로 지정할 수 있으며 백버튼으로 이전의 프래그먼트로 돌아갈 수 있으며 ViewModel을 지원하기에 UI관련 데이터를 공유할 수 있습니다. 이밖에도 여러 기능을 지원합니다.
Navigation 구성요소
호스트(NavHostFragment)
UI 즉 프래그먼트가 바뀌어지는 그릇을 의미합니다.
프래그먼트에서는 NavHostFragment를 이용하여 Host를 구현할 수 있습니다. 구현시에는 android:name="androidx.navigation.fragment.NavHostFragment" 및 app:defaultNavHost="true"는 시스템 뒤로 버튼을 NavHostFragment에 연결합니다. app:navGraph를 이용하여 NavHostFragment를 내비게이션 그래프와 연결합니다.
그래프(NavGraph)
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@+id/home_dest">
<fragment
android:id="@+id/home_dest"
android:name="com.example.android.codelabs.navigation.HomeFragment"
android:label="@string/home"
tools:layout="@layout/home_fragment">
</fragment>
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_one_fragment">
<argument
android:name="flowStepNumber"
app:argType="integer"
android:defaultValue="1"/>
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_two_dest">
</action>
</fragment>
<fragment
android:id="@+id/flow_step_two_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_two_fragment">
<argument
android:name="flowStepNumber"
app:argType="integer"
android:defaultValue="2"/>
<action
android:id="@+id/next_action"
app:popUpTo="@id/home_dest">
</action>
</fragment>
<fragment
android:id="@+id/deeplink_dest"
android:name="com.example.android.codelabs.navigation.DeepLinkFragment"
android:label="@string/deeplink"
tools:layout="@layout/deeplink_fragment">
<argument
android:name="myarg"
android:defaultValue="Android!"/>
</fragment>
</navigation>
앱 내의 모든 네비게이션 대상과 연결 방법을 정의하는 데이터 구조입니다.
어떤 목적지들이 있는지, 이동 중 어떤 액션을 취할 것인지, 어떤 데이터를 넘겨줄 것인지에 대한 정보가 담겨 있습니다.
비주얼 에디터를 제공하기 때문에 XML로 작성할 수 있으며 코드로도 해당 그래프를 구현할 수 있습니다.
컨트롤러(NavController)
모든 NavHost 가 개별적으로 가지고 있는 구성 요소인 컨트롤러는 대상 간 내비게이션, 딥 링크 처리, 백 스택 관리 등의 작업을 위한 메서드를 제공합니다.
프래그먼트에서는 이런 식으로 호스트로부터 컨트롤러를 받아올 수 있습니다.
목적지(NavDestination)
NavDestination은 NavGraph 내의 각 화면 또는 프래그먼트입니다.
NavGraph에 요소를 추가하게 되면 위의 그림처럼 NavDestination 클래스를 만들어 줍니다. 이는 Destination은 프래그먼트에서 이동 시에 사용할 수 있습니다.
build.gradle
dependencies {
def nav_version = "2.7.7" // 최신버전
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}
res/navigation/mobile_navigation.xml
비쥬얼 에디터나 xml을 이용하여 Navigation graph를 만듭니다.
해당 그래프를 만들 때 프래그먼트의 이동(Action)이나 넘겨줄 데이터(argument)등을 지정할 수 있습니다.
res/layout/activity_main.xml
액티비티나 프래그먼트에 fragment를 사용할수 있도록 호스트를 등록합니다.
이렇게 등록을 하게 되면 NavHostFragment 자체나 NavHostFragment를 상위 요소로 보유하는 뷰나 프래그먼트에서
위 함수들을 이용하여 컨트롤러에 접근을 할 수 있습니다.
navigate
navigate 함수는 컨트롤러를 이용하여 호스트의 화면을 바꾸는 동작을 말합니다.
// id 이용
findNavController().navigate(R.id.action_homeFragment_to_writeArticleFragment)
위코드처럼 resId이용하여 호출할 수도 있으며
val options = navOptions {
anim {
enter = R.anim.slide_in_right
exit = R.anim.slide_out_left
popEnter = R.anim.slide_in_left
popExit = R.anim.slide_out_right
}
}
// id 이용
findNavController().navigate(R.id.action_homeFragment_to_writeArticleFragment,null,options)
이런 식으로 옵션을 추가할 수도 있는데 이경우 애니메이션 같은 경우 xml에서 설정할 수 있습니다.
val bundle = Bundle().apply {
putString("key", "value")
}
findNavController().navigate(R.id.action_homeFragment_to_writeArticleFragment, bundle)
//---- writeArticleFragment
val str : String? = arguments?.getString("amount")
데이터 또한 graph에 argument tag를 추가한다면 값을 번들에 넣어 넘길 수도 있습니다.
safeArgs
안드로이드의 Jetpack Navigation 라이브러리에서 제공하는 기능 중 하나로, 컴파일 타임에 안전하게 전달되는 인자를 사용하여 내비게이션을 관리할 수 있도록 도와줍니다. SafeArgs를 사용하면, 프래그먼트 간의 데이터를 전달할 때 프로그래밍 오류를 줄이고, 타입 안정성을 보장할 수 있습니다.
val action = HomeFragmentDirections.actionHomeFragmentToWriteArticleFragment()
findNavController().navigate(action)
//option 추가
val options = navOptions {
anim {
enter = R.anim.slide_in_right
exit = R.anim.slide_out_left
popEnter = R.anim.slide_in_left
popExit = R.anim.slide_out_right
}
}
findNavController().navigate(action,options)
//argument 전달
findNavController().navigate(HomeFragmentDirections.actionHomeFragmentToArticleFragment(articleId = it.articleId.orEmpty()))
//수신
private val args: ArticleFragmentArgs by navArgs()
val articleId = args.articleId
참고
https://velog.io/@jjddww/AAC-Navigation-1
'안드로이드 > AAC(Android Architecture Components)' 카테고리의 다른 글
[AAC] Navigation - setupWithNavController (1) | 2024.06.15 |
---|---|
[AAC] Navigation 기능 구현 - 딥 링크 (0) | 2024.06.12 |
[AAC] Lifecycle 정의와 활용 (0) | 2024.06.07 |
[AAC] LiveData의 정의와 사용 (0) | 2024.06.06 |
[AAC] DataBinding 고급 기능 (1) | 2024.06.05 |