Jetpack Android Navigation Component 2.0 by Laurence de Villers
This talk will describe what is new in Android Navigation Component, how easy it’s to navigate between fragment et the pros and cons of using the Navigation Component.
◦ You need to make sure that both work together and follow Android Developer Guide override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { android.R.id.home -> { onBackPressed() //or finish() true } else -> super.onOptionsItemSelected(item) } } Or @Override public boolean onSupportNavigateUp() { onBackPressed(); return true; }
with an app based on the hierarchical relationship between screen. Back button • The system Back button is used to navigate, in reverse chronological order, through the history of screens the user has recently worked with. VS
android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> ... <fragment android:id="@+id/my_nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/navigation_graph" /> </LinearLayout> You need to specify if this navHost is the default. You can have multiple NavHost is you have more than one activity
the fragment swaps in the NavHostFragment You can call methods like navigate() or popBackStack() The NavController will translates these commands into the appropriate framework operations based on the type of destination you are navigating to or from If you call navigate() with an activity destination, the NavController calls startActivity() on your behalf
android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> On the activity_main.xml
val host: NavHostFragment = supportFragmentManager .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return val navController = host.navController NavigationUI.setupWithNavController(findViewById<NavigationView>(R.id.nav_view), navController) } On the MainActivity.kt override fun onSupportNavigateUp(): Boolean { // Allows NavigationUI to support proper up navigation or the drawer layout // drawer menu, depending on the situation return NavigationUI.navigateUp(findNavController(this, R.id.mainNavigationFragment), appBarConfiguration) }
object and builder classes for type-safe access to arguments specified for destinations and actions. val username = arguments?.getString("usernameKey") Is replace by val username = args.username
@androidx.annotation.Nullable ViewGroup container, @androidx.annotation.Nullable Bundle savedInstanceState) { ... this.talk = TalkFragmentArgs.fromBundle(getArguments()).getTalk(); ... } The plugin will generate a class {FragmentWithArgs}Args
what are the parameter you need to pass for a destination. • You don’t need to cast serializable and parcelable. (You can specify directly a child of those classes) • You can pass Enum Cons • Proguard ◦ You need to prevent all your safe Args (Parcelable, Serializable and Enum class) to be obfuscated
onCreateAnimator(int transit, boolean enter, int nextAnim) { … } • You can shared Element for transition FragmentNavigator.Extras navigatorExtras = new FragmentNavigator.Extras.Builder() .addSharedElement(image, "imageName").build(); Navigation.findNavController(v).navigate(action, navigatorExtras); • And it easy to add animations for transition between screens
Deeplink with the Navigation Component • Explicite ◦ Will recreate all the stack following your graph to the destination of your deeplink. ◦ Is for Notification, Widget, App Shortcut • Implicite ◦ If FLAG_ACTIVITY_NEW_TASK is not set, will open the fragment on top of your current navigation
pendingIntent val args = Bundle() args.putString("myarg", "From Widget"); val pendingIntent = NavDeepLinkBuilder(context) .setGraph(R.navigation.mobile_navigation) .setDestination(R.id.deeplink_dest) .setArguments(args) .createPendingIntent() remoteViews.setOnClickPendingIntent(R.id.deep_link_button, pendingIntent) You can also use navController to create the deeplink Navigation.findNavController(v).createDeepLink() .setGraph(R.navigation.mobile_navigation) .setDestination(R.id.deeplink_dest).createPendingIntent();
add the Nav-graph in the Manifest <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <application ... > <activity name=".MainActivity" ...> ... <nav-graph android:value="@navigation/nav_graph" /> ... </activity> </application> </manifest> When building your projet, all <intent-filter> elements will be generated by the nav-graph <fragment android:id="@+id/talkFragment" android:name="com.montreal.wtm.ui.fragment.TalkFragment" android:label="content_talk" tools:layout="@layout/content_talk"> <argument android:name="talk" app:argType="com.montreal.wtm.model.Talk" /> <deepLink android:id="@+id/deepLink" app:uri="wtm://talk"/> </fragment>
proper up navigation or the drawer layout // drawer menu, depending on the situation override fun onSupportNavigateUp(): Boolean { return findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration) } Everything function that hooks navigation drawer, bottom nav bar with the NavController is now on the class NavigationUI override fun onSupportNavigateUp(): Boolean { return NavigationUI.navigateUp(findNavController(this, R.id.mainNavigationFragment), appBarConfiguration) } 2.0.0