Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Navigation 살펴보기

Navigation 살펴보기

'19년 GDG Android at Pangyo! (4월 밋업)의 'Navigation 살펴보기' 세션 발표자료입니다.

Navigation 살펴보기(more):
https://link.medium.com/gTVrhA4GjW

Sample Projects:
https://github.com/fornewid/GDGAndroid-atPangyo-2019-Navigation-Sample

Sungyong An

April 30, 2019
Tweet

More Decks by Sungyong An

Other Decks in Programming

Transcript

  1. Navigation이란? • Android Jetpack (’18.5 ~ ’19.3(Stable) ~ 현재) •

    앱 내의 화면 탐색을 다루는 Component • 레이아웃처럼 XML로 Navigation Graph를 관리 Link: https://youtu.be/8GCXtCjtg40 https://youtu.be/2k8x8V77CrU
  2. Navigation 클래스, 인터페이스 • NavHost / NavController • NavGraph •

    Navigator • NavDestination • NavDirections / NavArgs • NavigationUI <?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" android:id="@+id/navigation" app:startDestination="@+id/splash"> <fragment android:id="@+id/splash" android:name="soup.gdg.navigation.sample.ui.splash.SplashFragment" tools:layout="@layout/fragment_splash" /> <fragment android:id="@+id/login" android:name="soup.gdg.navigation.sample.ui.login.LoginFragment" tools:layout="@layout/fragment_login"> <argument android:name="nextDestinationIsUp" android:defaultValue="false" app:argType="boolean" /> </fragment> <fragment android:id="@+id/home" android:name="soup.gdg.navigation.sample.ui.home.HomeFragment" android:label="@string/title_home" tools:layout="@layout/fragment_home" /> <fragment android:id="@+id/detail" android:name="soup.gdg.navigation.sample.ui.detail.DetailFragment" tools:layout="@layout/fragment_detail"> <argument android:name="movieId" app:argType="string" app:nullable="false" /> <deepLink app:uri="origin://detail/{movieId}" /> </fragment> <fragment android:id="@+id/settings" android:name="soup.gdg.navigation.sample.ui.settings.SettingsFragment" tools:layout="@layout/fragment_settings" /> <activity android:id="@+id/web" android:name="soup.gdg.navigation.sample.ui.web.WebActivity" tools:layout="@layout/activity_web"> <argument android:name="data" app:argType="soup.gdg.navigation.sample.ui.web.WebScene" /> </activity> <include app:graph="@navigation/nav_graph_profile" /> <dialog_fragment android:id="@+id/login_confirm" android:name="soup.gdg.navigation.sample.ui.login.LoginConfirmDialogFragment" /> </navigation> = Fragment = Intent / Bundle = UI Helper = Activity / FragmentManager
  3. 기본 원칙 • 고정된 시작점 • Navigation 상태는 Destination Stack으로

    표현 • App Task 내에서 Up과 Back은 동일 • Up 버튼은 App을 종료 불가능 • 딥링크는 일반 탐색과 동일하게 처리 Link: https://developer.android.com/guide/navigation/navigation-principles App Task … Back or Up App Task … DeepLink
  4. Navigate Forward Activity Activity startActivity Fragment Fragment ft.replace navigate NavDestination

    NavDestination • 다음 화면으로 이동하기 Bundle Bundle Bundle NavDirections NavArgs
  5. Navigate Forward // For Activity val intent = Intent(this, LoginActivity::class.java)

    startActivity(intent) // For Fragment val fragment = LoginFragment() fragmentManager .beginTransaction() .replace(R.id.container, fragment) .addToBackStack("back stack name") .commit() intent.putExtra("name", “value")
 
 
 fragment.arguments = bundleOf("name" to "value")
  6. Navigate Forward // Without Arguments navController.navigate(R.id.login) navController.navigate( SplashFragmentDirections.actionToLogin()) // With

    Arguments val arguments = bundleOf("name" to "value") navController.navigate(R.id.login, arguments) navController.navigate( SplashFragmentDirections.actionToLogin(/* name */ “value") ) <!-- In Navigation XML --> <action android:id="@+id/action_to_login" app:destination=“@id/login" /> val navController = findNavController() <!-- In Navigation XML --> <argument android:name="name" app:argType="string" />
  7. Navigate Backward Activity Activity finish Fragment Fragment fm.popBackStack navigateUp popBackStack

    NavDestination NavDestination Result X X " • 이전 화면으로 되돌아가기
  8. Navigate Backward val navController = findNavController() navController.navigateUp() — (1) navController.popBackStack()

    — (2) navController.popBackStack( /* destinationId */ R.id.home, /* inclusive */ false ) — (3) App Task … (1,2,3) (2,3) (3)
  9. Find NavController • 모든 요청은 NavController를 통한다 • Kotlin: Link:

    https://developer.android.com/guide/navigation/navigation-getting-started#navigate_to_a_destination Fragment.findNavController() View.findNavController() Activity.findNavController(viewId: Int)
  10. // For Kotlin val navController = findNavController() navController.navigate( NavigationDirections.actionToLogin() )

    Navigate Forward (+ Pop Up) <!-- In Navigation XML --> <action android:id="@+id/action_to_login" app:destination="@id/login" app:popUpTo="@id/splash" app:popUpToInclusive="true" /> NavigationDirections.actionToLogin(), NavOptions.Builder() .setPopUpTo(R.id.login, true) .build() ) navOptions { popUpTo(R.id.splash) { inclusive = true } } }
  11. Navigate Forward (+ Single Top) Before A After B B

    • 같은 화면을 연속으로 쌓지 않고, 다음 화면으로 이동하기
  12. // For Kotlin val navController = findNavController() navController.navigate( NavigationDirections.actionToDetail(id) )

    Navigate Forward (+ Single Top) <!-- In Navigation XML --> <action android:id="@+id/action_to_detail" app:destination="@id/detail" app:launchSingleTop="true" /> NavigationDirections.actionToDetail(id), NavOptions.Builder() .setLaunchSingleTop(true) .build() ) navOptions { launchSingleTop = true } )
  13. Navigation Structure NavHost (NavHostFragment) NavController NavGraph NavigatorProvider Navigator NavBackStackEntry NavDestination

    ‘B’ NavDestination ‘A’ NavDirections NavArgs • 직접 사용할 때는 NavController, NavDirections, NavArgs만 알면 된다.
  14. NavGraph • 앱 화면들을 정의하는 리소스 파일
 
 ㄴ res/navigation/{graph_file_name}.xml

    • NavDestination는 Fragment / Activity / NavGraph가 가능 • 각 화면으로의 Action을 정의할 수 있음 • 각 화면의 Arguments를 정의할 수 있음
  15. NavGraph (1/2) <navigation android:id="@+id/navigation" app:startDestination="@+id/splash"> <fragment android:id="@+id/splash" android:name=".ui.splash.SplashFragment" tools:layout="@layout/fragment_splash"> <action

    android:id="@+id/action_to_login" app:destination="@id/login" app:enterAnim="@anim/slide_in_right" app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim=“@anim/slide_out_right" /> </fragment> ... <— NavGraph <- NavGraph ID <— Fixed start destination
 <— Fragment NavDestination <- NavDestination ID
 
 
 <— A NavAction in NavDirections (Local) <- NavAction ID
 <| Transition
 | Animations
 | of NavAction
 |
  16. NavGraph (2/2) <activity android:id="@+id/web" android:name=".ui.web.WebActivity"> <argument android:name="data" app:argType=".ui.web.WebScene" app:nullable="false" />

    </activity> <include app:graph="@navigation/nav_graph_profile" /> <action android:id="@+id/action_to_login" app:destination="@id/login" /> </navigation> <— Activity NavDestination
 
 
 <— A field of NavArgs
 
 
 
 
 // Nested NavGraph
 
 <— A NavAction for NavDirections (Global)
  17. SafeArgs (NavArgs) • Fragment 또는 Activity의 Bundle에서 Arguments 꺼내기 •

    Kotlin: Link: https://developer.android.com/guide/navigation/navigation-pass-data#Safe-args val args: WebActivityArgs by navArgs() args.data // WebScene
  18. NavHost • NavController 제공하는 컨테이너 • NavHostFragment라는 구현체를 기본 제공

    • Fragment 계층 구조:
 
 MainActivity • NavHostFragment • SplashFragment • LoginFragment • …
  19. NavHost <!-- In Layout XML --> <fragment android:id="@+id/navHostFragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent"

    android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" /> ũ app:defaultNavHost="true" // For Kotlin val hostFragment = NavHostFragment.create(R.navigation.nav_graph) supportFragmentManager.beginTransaction() .replace(R.id.nav_host, hostFragment) .setPrimaryNavigationFragment(hostFragment) .commit()
  20. 못다한 얘기들 • Handling Shared Elements • Handling Back Pressed

    Events • NavArgs using @Parcelize class • NavGraph Scope ViewModel • Dialog NavDestination • NavigationUI with multiple start destinations • Handling SystemUI • Handling NavResult? Link: https://link.medium.com/gTVrhA4GjW
  21. Dependencies (AndroidX) def nav_version = “2.1.0-alpha02" // 2.0.0 (Stable) //

    For Java implementation "androidx.navigation:navigation-fragment:$nav_version" implementation "androidx.navigation:navigation-ui:$nav_version"
 // For Kotlin implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version" /* SafeArgs - project/build.gradle */ classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" // For Kotlin apply plugin: “androidx.navigation.safeargs.kotlin" // For Java apply plugin: “androidx.navigation.safeargs" Link: https://developer.android.com/jetpack/androidx/releases/navigation
  22. Dependencies (Pre-AndroidX) def nav_version = "1.0.0" // For Java implementation

    "android.arch.navigation:navigation-fragment:$nav_version" implementation "android.arch.navigation:navigation-ui:$nav_version" // For Kotlin implementation "android.arch.navigation:navigation-fragment-ktx:$nav_version" implementation "android.arch.navigation:navigation-ui-ktx:$nav_version" /* SafeArgs - project/build.gradle */ classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:$nav_version" Link: https://developer.android.com/jetpack/androidx/releases/navigation#pre-androidx_dependencies
  23. Conclusion • 화면 탐색을 다루는 '공식적인' 방법 + 1 •

    직접적인 FragmentTransaction 필요 X • 다수의 Fragments 관리가 필요한 경우, 고려해볼 것 • 다음/이전 화면으로의 자유로운 이동 기능 • 아쉬운 부분은 존재 (Ex. 이전 화면으로 결과 전달 불가능) • 사실상 AndroidX로 전환 필요
  24. More References • Version Release
 https://developer.android.com/jetpack/androidx/releases/navigation • Official Guide
 https://developer.android.com/guide/navigation

    • CodeLab
 https://codelabs.developers.google.com/codelabs/android-navigation • Source Code
 android-arch-navigation-release
 androidx-navigation-release