• Stars
    star
    393
  • Rank 109,518 (Top 3 %)
  • Language
    Kotlin
  • License
    MIT License
  • Created about 5 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Tutorials about Navigation Components to learn using nav graphs, adding top menus, passing arguments via safe args, combining with different Material Design widgets such as BottomNavigationView, Toolbar, ViewPager2, TabLayout and dynamic feature module navigation with DynamicNavHostFragment and examining Memory Leaks.

Navigation Components Tutorials

Tutorials for learning Navigation Components starting with simple set up, continues with adding top menus, passing arguments via navigation graphs and combining them with different Material Design widgets such as BottomNavigationView, Toolbar, ViewPager2, TabLayout and dynamic feature module navigation with DynamicNavHostFragment.

Overview

Tutorial Coverage

Tutorial0-0MaterialDesign

Covers basic BottomNavigationView and ViewPager usage without any navigatiom components. This is a little bit like warm up before moving to more complex ones including navigation with ViewPager2

Tutorial1-Navigation-NavGraph

Covers how to use create navigation graph nav_graph.xml inside navigation folder, and NavHostFragmentin activity_main.xml layout file.

Note

One important note to add is navigation uses FragmentTransaction.replace() to navigate next fragment inside specified NavHostFragment

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"

        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

There are multiple ways to navigate from one fragment to another using a NavController, for instance


buttonCenter?.setOnClickListener {

    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(R.id.middle1_dest, null, options)
}

Check out this tutorial if you wish to get familiar with basic consepts, animation and navigating with popUpToand popUpToInclusive

Tutorial1-2Navigation-NestedNavGraph

Uses seperate and nested fragments with each it's own navigation graph.

nav_graph is the main graph for navigation has navigation to CameraFragment or other graphs such as nav_graph_dashboard or nav_graph_home Nested graphs are part of the same navHostFragment?.childFragmentManager

Tutorial1-3Navigation-NestedNavHost

Covers how nested graphs with their own back stack or NavHostFragment work. You can check out both main and home childFragmentManager back stack entry and fragment count by examining Toast or log messages.

Note

Main graph back stack is controlled by NavHostFragment.getChildFragmentManager

When a nested navigation graph or NavHostFragment is added it's back stack is retrieved using a childFragmentManager.

When a fragment is from a nested navigation graph is on screen when you navigate back or forth it's current position changes only for the current NavHostFragment, main back stack does not change.

val callback = object : OnBackPressedCallback(false) {

   override fun handleOnBackPressed() {

       // Get NavHostFragment
       val navHostFragment =
           childFragmentManager.findFragmentById(nestedNavHostFragmentId)
       // ChildFragmentManager of the current NavHostFragment
       val navHostChildFragmentManager = navHostFragment?.childFragmentManager

       // Check if it's the root of nested fragments in this navhosts
       if (navController?.currentDestination?.id == navController?.graph?.startDestination) {

           /*
               Disable this callback because calls OnBackPressedDispatcher
                gets invoked  calls this callback  gets stuck in a loop
            */
           isEnabled = false
           requireActivity().onBackPressed()
           isEnabled = true

       } else if (isVisible) {
           navController?.navigateUp()
       }

   }
}

Note

Back navigation does NOT work for the first fragment in back stack of HomeNavHostFragment for this example, because

if (navController!!.currentDestination == null || navController!!.currentDestination!!.id == navController!!.graph.startDestination) {
   navController?.navigate(R.id.homeFragment1)
}

and start destination is HomeNavHostFragmentitself , but last fragment, currentDestination on graph is HomeFragment1 when back button is pressed while HomeFragment2 is on screen.

Change app:startDestination="@id/home_dest" to app:startDestination="@id/homeFragment1" to solve back press issue for HomeNavHostFragment, it's just set to demonstrate how start destination change back press.

<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/nav_graph_home"
      app:startDestination="@id/home_dest">

  <fragment
          android:id="@+id/home_dest"
          android:name="com.smarttoolfactory.tutorial1_3navigation_nestednavhost.navhost.HomeNavHostFragment"
          android:label="HomeHost"
          tools:layout="@layout/fragment_navhost_home" />

  <fragment
          android:id="@+id/homeFragment1"
          android:name="com.smarttoolfactory.tutorial1_3navigation_nestednavhost.blankfragment.HomeFragment1"
          android:label="HomeFragment1"
          tools:layout="@layout/fragment_home1">

  </fragment>

</navigation>

Tutorial6-0NavigationUI-ViewPager

Navigation Architecture

MainActivity (Appbar + Toolbar)
|- MainNavHost
    |
    | FragmentViewPagerContainer(ViewPager2 + TabLayout)
        |- HomeFragment1 -> HomeFragment2 -> HomeFragment3
        |- DashboardFragment1 -> DashboardFragment2 -> DashboardFragment3

Covers how to create a ViewPager2with navigation in main back stack, in this example ViewPager2pages do not have their own back stacks. It's covered in tutorial Tutorial6-2.

Tutorial6-1NavigationUI-ViewPager

Same as previous tutorial except only with one difference, data binding is used for binding.

Note

Data binding that is not null(or non-nullable) after Fragment.onDestroyView when ViewPager2is inside a fragment causing leak canary to show data binding related MEMORY LEAK for this fragment when used in ViewPager2. Also you need to set adapter of ViewPager2 either to prevent memory leaks, and another one is due to TabLayouts which is covered in later sections. Check out this stackoverflow question for more details.

Tutorial6-2NavigationUI-NestedNavHost

Navigation Architecture


 MainActivity (Appbar + Toolbar)
    |- MainNavHost
       |
       |- ViewPagerContainerFragment(ViewPager2 + TabLayout)
       |   |- HomeNavHostFragment
       |   |  |- HF1 -> HF2 -> HF3
       |   |
       |   |- DashboardNavHostFragment
       |   |  |- DF1 -> DF2 -> DF3
       |   |
       |   |- NotificationHostFragment
       |   |  |- NF1 -> NF2 -> NF3
       |   |
       |   |-LoginFragment1
       |
       |- LoginFragment1 -> LoginFragment2

Covers ViewPager2 and it's pages each with it's own back stack or navigation graphs.

NavHostFragment use NavController to navigate back/forth in any page.

Note

This tutorial has very important aspects for ViewPager2 navigation

  1. Creating NavHostFragment for each page and can navigate inside them, each page has it's own nav graph.

    in each layout file NavHostFragment inside is retrieved using

            val nestedNavHostFragment =
                childFragmentManager.findFragmentById(nestedNavHostFragmentId) as? NavHostFragment
            navController = nestedNavHostFragment?.navController`
    

    HomeNavHostFragment uses the first fragment that is displayed on screen **HomeFragment1 while DashboardNavHostFragment uses graph with itself as start destination so it should check for the NavController.getCurrentDestination() to navigate to it when device rotated

    LoginFragment1 is added to main graph, because of that appbar back navigation only works with the ViewPagerContainerFragment's NavController

  2. How to use back navigation with OnBackPressedCallback, there is an alternative and more simple way to handle back navigation for ViewPager2 but this also a way to keep in mind if more customization is required. If you do not handle back navigation Activity's back press gets called and application starts from onCreate.

  3. Checking out memory leaks with data binding, ViewPager2 adapter and lifecylce.

    • You should set data binding to null or you will get memory leaks for this ViewPager2 which is itself also inside a fragment

    • You should set ViePager2's adapter to null in onDestroyView

    • πŸ”₯ You should use ChildFragmentStateAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle), not the one that takes Fragment as parameter. And use view's lifecycle instead of setting Fragment's lifecycle.

    viewPager.adapter =
                       ChildFragmentStateAdapter(childFragmentManager, viewLifecycleOwner.lifecycle)
    

Refer to this stackoverflow question for more details.

Tutorial6-3NavigationUI-ViewPager2-Appbar-NestedNavigation-LiveData

Navigation Architecture

 MainActivity(Appbar + Toolbar + TabLayout + ViewPager2)
   |
   |- HomeNavHostFragment
   |  |- HF1 -> HF2 -> HF3
   |
   |- DashboardNavHostFragment
   |  |- DF1 -> DF2 -> DF3
   |
   |- NotificationHostFragment
      |- NF1 -> NF2 -> NF3

In this tutorial MainActivity has it's appbar that navigation is controlled using the NavController retrieved from NavHostFragment via LiveData

Note

There is an issue with rotation, when device rotated ActivityFragmentStateAdapter.createFragment method is not called and it's not possible to access NavController of newly created fragments. If you do not wish to have a rotatable app you can use live data or ViewModel to get current NavController to change appbar title and get other properties of NavController. LiveData is observed in MainActivity to set appbar title

Tutorial6-4NavigationUI-ViewPager2-FragmentToolbar-NestedNavigation

Navigation Architecture

 MainActivity
    |- MainNavHost
       |
       |- ViewPagerContainerFragment(ViewPager)
           |
           |- HomeNavHostFragment(Appbar + Toolbar)
           |  |- HF1 -> HF2 -> HF3
           |
           |- DashboardNavHostFragment(Appbar Toolbar)
           |  |- DF1 -> DF2 -> DF3
           |
           |- NotificationHostFragment(Appbar Toolbar)
              |- NF1 -> NF2 -> NF3

In this tutorial each NavHostFragment has it's own toolbar They can navigate back with back arrow when navigated to an inner/nested fragment in pages of ViewPager

Using FragmentStateAdapter.registerFragmentTransactionCallback with FragmentStateAdapter solves back navigation instead of using OnBackPressedCallback.handleOnBackPressed in every NavHostFragment as answered here

init {
    // Add a FragmentTransactionCallback to handle changing
    // the primary navigation fragment
    registerFragmentTransactionCallback(object : FragmentTransactionCallback() {
        override fun onFragmentMaxLifecyclePreUpdated(
            fragment: Fragment,
            maxLifecycleState: Lifecycle.State
        ) = if (maxLifecycleState == Lifecycle.State.RESUMED) {

            // This fragment is becoming the active Fragment - set it to
            // the primary navigation fragment in the OnPostEventListener
            OnPostEventListener {
                fragment.parentFragmentManager.commitNow {
                    setPrimaryNavigationFragment(fragment)
                }
            }

        } else {
            super.onFragmentMaxLifecyclePreUpdated(fragment, maxLifecycleState)
        }
    })
}

If defaultNavHost is not set to true true for any NavHostFragments by setting app:defaultNavHost="true" in xml or programmatically snippet above will not work.

Tutorial6-5NavigationUI-ViewPager2-FragmentToolbar-MixedNavigation

Navigation Architecture

MainActivity
   |- MainNavHost
      |
      |- ParenNavHost((Appbar + Toolbar)
          |
          |- ViewPagerContainerFragment(ViewPager2)
          |   |
          |   |- HomeNavHostFragment(Appbar + Toolbar)
          |   |  |- HF1 -> HF2 -> HF3
          |   |
          |   |- DashboardNavHostFragment(Appbar + Toolbar)
          |   |  |- DF1 -> DF2 -> DF3
          |   |
          |   |- NotificationHostFragment(Appbar + Toolbar)
          |   |  |- NF1 -> NF2 -> NF3
          |   |
          |   |-LoginFragment1
          |
          |- LoginFragment1 -> LoginFragment2

In this tutorial each NavHostFragment has it's own toolbar, also ParentNavHostFragment has it's own toolbar either.

LoginFragment2 in this example is added to back stack of ParentNavHostFragment because of that it does not have any association with toolbar in ViewPagerContainerFragment

ParentNavHostFragment's role is to have it's own Appbar to contain login fragments and navigate through them using Appbar. Without ParentNavHostFragment we navigate to LoginFragment2 that has no Appbar.

Visibility of ParentNavHostFragment is changed via liveData of AppbarViewModel

However, there is an issue whenever Toolbar that is not belong to fragments appear or disappear.

Tutorial6-6NavigationUI-ViewPager2-Appbar-MixedNavigation-ViewModel

Navigation Architecture

MainActivity
  |- MainNavHostFragment
     |
     |- ParenNavHostFragment(Appbar + Toolbar) Here because we wish to have toolbar inside Fragment
         |
         |- ViewPagerContainerFragment(TabLayout + ViewPager2)
         |   |
         |   |- HomeNavHostFragment
         |   |  |- HF1 -> HF2 -> HF3
         |   |
         |   |- DashboardNavHostFragment
         |   |  |- DF1 -> DF2 -> DF3
         |   |
         |   |- NotificationHostFragment
         |   |  |- NF1 -> NF2 -> NF3
         |   |
         |   |-LoginFragment1
         |
         |- LoginFragment1 -> LoginFragment2

In this tutorial, only ParentNavHostFragment has Appbar and Toolbar. Navigation of individual NavHostFragments is done via LiveData belong to AppbarViewModel.currentNavController which returns NavController of current NavHostFragment on screen due. Current NavController is set onResume to make sure to set it only when the current fragment is visible, it's instead of checking if fragment is on screen and visible.

ParentNavHostFragment's role is to have it's own Appbar to contain login fragments and navigate through them using Appbar. Without ParentNavHostFragment we navigate to LoginFragment2 that has no Appbar if it's inside ViewPagerContainerFragment.

It can be done by putting Appbar to MainActivity but purpose here is to put Appbar + Toolbar inside a fragment to be able to use with BottomNavigationView for instance

Tutorial7-1BNV-ViewPager2-NestedNavigation

Navigation Architecture

 MainActivity(BottomNavigationView + ViewPager2 + Appbar + Toolbar)
       |- HomeNavHostFragment
       |   |- HF1 -> HF2 -> HF3
       |
       |- DashboardNavHostFragment
       |   |- DF1 -> DF2 -> DF3
       |
       |- NotificationHostFragment
       |   |- NF1 -> NF2 -> NF3

In this example BottomNavigationView selects which page of ViewPager2 should be opened using BottomNavigationView.setOnNavigationItemSelectedListener

Appbar title is changed using LiveData AppbarViewModel.currentNavController of visible NavHostFragment on screen of ViePager2 page

Change current nav controller to set appbar title

appbarViewModel.currentNavController.observe(this, Observer { it ->

    it?.let { event: Event<NavController> ->
        event.getContentIfNotHandled()?.let { navController ->
            val appBarConfig = AppBarConfiguration(navController.graph)
            dataBinding.toolbar.setupWithNavController(navController, appBarConfig)
        }
    }
})

Tutorial7-2BNV-ViewPager2-ComplexArchitecture

Navigation Architecture

     MainActivity(BottomNavigationView + ViewPager2 + Appbar + Toolbar)
        |
        |- ViewPagerContainerFragment(TabLayout + ViewPager2)
        |      |
        |      |- HomeNavHostFragment
        |      |  |- HF1 -> HF2 -> HF3
        |      |
        |      |- DashboardNavHostFragment
        |      |  |- DF1 -> DF2 -> DF3
        |      |
        |      |- NotificationHostFragment
        |      |  |- NF1 -> NF2 -> NF3
        |      |
        |      |-LoginFragment1
        |
        |- DashboardNavHostFragment
        |   |- DF1 -> DF2 -> DF3
        |
        |- NotificationHostFragment
        |   |- NF1 -> NF2 -> NF3

This example is combination of Tutorial6-6 and Tutorial 7-1

First tab of the BottomNavigationView is ViewPagerContainerFragment which has a ViewPager2 that has it's own pages with each it's own back stack setting NavController is done both using AppbarViewModel and BottomNavigationView.setupWithNavController in the NavigationExtensions code for setting BottomNavigationView back stack.

Tutorial7-3BNV-ViewPager2-FragmentToolbar-MixedNavigation

Navigation Architecture

  MainActivity
    |- MainNavHostFragment
         |
         |- ContainerNavHostFragment(BottomNavigationView  Appbar + Toolbar)
         |    |
         |    |- ViewPagerContainerFragment(ViewPager2 + TabLayout)
         |    |      |
         |    |      |- PostVerticalNavHost
         |    |      |  |- PostVerticalFragment -> PostDetailFragment
         |    |      |
         |    |      |- PostHorizontalNavHost
         |    |      |  |- PostHorizontalFragment -> PostDetailFragment
         |    |      |
         |    |      |- PostGridNavHostFragment
         |    |      |  |- PostGridFragment
         |    |      |
         |    |      |- PostStaggerNavHostFragment
         |    |      |  |- PostStaggeredFragment
         |    |      |
         |    |      |- NotificationHostFragment
         |    |      |  |- NF1 -> NF2 -> NF3
         |    |      |
         |    |      |- LoginFragment1
         |    |
         |    |
         |    |- DashboardNavHostFragment
         |    |   |- DF1 -> DF2 -> DF3
         |    |
         |    |- NotificationHostFragment
         |    |  |- NF1 -> NF2 -> NF3
         |    |
         |    |- &PostGridFragment -> PostDetailFragment
         |    |
         |    |- &LoginFragment1 -> LoginFragment2
         |
         |
         |- &PostStaggeredFragment -> PostDetailFragment

In this tutorial BottomNavigationView is inside MainFragment. MainActivity can navigate to a different fragment other than the MainFragment using nav_graph main destinations.

Navigation is layered, fragments annotated with & display that hey navigate at that level, not actually added to that hierarchy.

For instance, PostStaggeredFragment which is in ViewPager2 calls snippet below to get main NavController to navigate in main navigation graph requireActivity().findNavController(R.id.main_nav_host_fragment).navigate(R.id.action_mainFragment_to_postDetailFragment, bundle)

PostGridFragment which is in ViewPager2 gets PNavControllerP that belong to ViewPagerContainerFragment via parentFragment?.parentFragment?.findNavController() and navigates from ViewPagerContainerFragment to PostDetailFragment

πŸ”₯πŸ”₯πŸ”₯ Important

If you navigate from PostStaggeredFragment to PostDetailFragment fragment you will see that memory leak occurs. It happens due to BottomNavigationView.setupWithNavControllerfunction inNavigationExtensions.ktclass leaking because of listeners not being unregistered in extension functions inonDestroyView``` of fragment.

Check out Tutorial8-2 for solution for this issue

Tutorial8-1DynamicFeatures-Navigation

This tutorial to navigate to dynamic feature module from App, navigate from dynamic feature module gallery to favorites.

Steps to create dynamic navigation from app to dynamic feature modules, or from one dynamic feature module to another

  1. Replace android:name="androidx.navigation.fragment.NavHostFragment" with android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment" for the layouts
<androidx.fragment.app.FragmentContainerView
    android:id="@+id/nestedDashboardNavHostFragment"
    android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
    app:defaultNavHost="true"
    app:navGraph="@navigation/nav_graph_dashboard"/>
  1. Add dynamic navigation with <include>, <activity> or as fragmentt to any navigation graph
    • You don't have to use an id, but if you do, same id defined here must be used in dynamic feature module, or will get an error.
    • Add package name of dynamic feature module
    • Add nav graph name in navigation folder of dynamic feature module
    • Add module name which is also in app's build.gradle file
    • Optionally add arguments to pass to dynamic feature module fragments
<!-- gallery dynamic feature module-->
<include-dynamic
    android:id="@+id/nav_graph_gallery"
    android:name="com.smarttoolfactory.gallery"
    app:graphResName="nav_graph_gallery"
    app:moduleName="gallery">
    <argument
        android:name="count"
        android:defaultValue="0"
        app:argType="integer" />
</include-dynamic>
  1. In dynamic feature module navigation creata navigation graph to navigate in feature module fragmnent or navigate to other dynamic feature modueles, and passing arguments and getting the result from a fragment with savedStateHandle.
    • id in dynamic feature module should not contain +, because you are using the same id resource defined in app or the snippet above. If you do you will have the error i got here
<?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"
    android:id="@id/nav_graph_gallery"
    app:moduleName="gallery"
    app:startDestination="@id/galleryFragment1">

    <fragment
        android:id="@+id/galleryFragment1"
        android:name="com.smarttoolfactory.gallery.GalleryFragment1"
        android:label="GalleryFragment1">
        <action
            android:id="@+id/action_galleryFragment1_to_galleryFragment2"
            app:destination="@id/galleryFragment2" />
        <action
            android:id="@+id/action_galleryFragment1_to_nav_graph_favorites"
            app:destination="@id/nav_graph_favorites" />
    </fragment>

    <!-- favorite dynamic feature module-->
    <include-dynamic
        android:id="@id/nav_graph_favorites"
        android:name="com.smarttoolfactory.favorites"
        app:graphResName="nav_graph_favorites"
        app:moduleName="favorites" >
        <argument
            android:name="count"
            app:argType="integer"
            android:defaultValue="0" />
    </include-dynamic>
</navigation>

HomeFragment1 listen savedStateHandle with findNavController().currentBackStackEntry?.savedStateHandle.getLiveData<Int>

HomeFragment2 and GalleryFragment sets result with findNavController().previousBackStackEntry?.savedStateHandle?.set("count", count)

Tutorial8-2DynamicFeatures-ComplexArchitecture

Navigation Architecture

  MainActivity
    |- MainNavHostFragment
         |
         |- ContainerNavHostFragment(BottomNavigationView  Appbar + Toolbar)
         |    |
         |    |- ViewPagerContainerFragment(ViewPager2 + TabLayout)
         |    |      |
         |    |      |- PostVerticalNavHost
         |    |      |  |- PostVerticalFragment -> PostDetailFragment
         |    |      |
         |    |      |- PostHorizontalNavHost
         |    |      |  |- PostHorizontalFragment -> PostDetailFragment
         |    |      |
         |    |      |- PostGridNavHostFragment
         |    |      |  |- PostGridFragment
         |    |      |
         |    |      |- PostStaggerNavHostFragment
         |    |      |  |- PostStaggeredFragment
         |    |      |
         |    |      |- NotificationHostFragment
         |    |      |  |- NF1 -> NF2 -> NF3
         |    |      |
         |    |      |- LoginFragment1
         |    |
         |    |
         |    |- DashboardNavHostFragment
         |    |   |- DF1 -> DF2 -> DF3
         |    |
         |    |- NotificationHostFragment
         |    |  |- NF1 -> NF2 -> NF3
         |    |
         |    |- &PostGridFragment -> PostDetailFragment
         |    |
         |    |- &LoginFragment1 -> LoginFragment2
         |    |
         |    |- NF1 | 2F2 -> Camera Dynamic Feature
         |
         |
         |- DF1 | 2F2 -> Photo Dynamic Feature
         |
         |- NF1 | 2F2 -> Camera Dynamic Feature
         |
         |- &PostStaggeredFragment -> PostDetailFragment

         // Photos Dynamic feature navigate to Camera Dynamic feature
         |- Photos Dynamic Feature -> Camera Dynamic Feature

In this tutorial same as Tutorial 7-3 navigation layered, and navigation from app module to dynamic features, or navigation from Photos dynamic feature module to Camera dynamic feature module is available.

There are two versions of main fragment.

One with MainFragment which uses BottomNavigationView extension, and MainFragmentWithViewPager uses ViewPager2 to create back stack of BottomNavigationView.

Note

πŸ”₯ Since DynamicNavHostFragment used instead of NavHostFragment another extension should be written that creates fragments that have [DynamicNavHostFragment] in fragments.

If BottomNavigationView extension is used with DynamicNavHostFragment it returns the error below

  Caused by: java.lang.IllegalStateException: Could not find Navigator with name "include-dynamic". You must call NavController.addNavigator() for each navigation type.
     at androidx.navigation.NavigatorProvider.getNavigator(NavigatorProvider.java:98)
     at androidx.navigation.NavInflater.inflate(NavInflater.java:107)
     at androidx.navigation.NavInflater.inflate(NavInflater.java:141)
     at androidx.navigation.NavInflater.inflate(NavInflater.java:88)

Also, since extension is not used, observe that not getting MEMORY LEAK that was present in Tutorial7-3

ToDos:

  • Use nav graph ViewModel by navGraphViewModels, couldn't find it yet
  • Solve setFragmentResultListener issue to get result from a framgent on back press, and use instead of savedStateHandle
  • Use saveStateHandle or save fragment state in Tutorial 8-2 when ViewPager2 moves away from viewPort
  • There is a performance issue in Tutorial 8-2 when navigate back from StaggerPostListFragment, or navigating back to fragment main
  • Use BottomNavigationView extension with DynamicNavHostFragment, or create another extension for dynamic feature modules

More Repositories

1

Jetpack-Compose-Tutorials

πŸš€πŸ§¨πŸ“ Series of Tutorials to learn about Jetpack Compose with subjects Material Widgets, Layout, SubcomposeLayout, custom layouts, State, custom rememberable, recomposition, LaunchedEffect, side-effects, Gesture, Animation, Navigation, Canvas, UIs like whatsapp and others.
Kotlin
2,797
star
2

Animation-Tutorials

πŸ­πŸš€πŸ’— Tutorials about animations with Animators, Animated Vector Drawables, Shared Transitions, and more
Kotlin
803
star
3

Compose-Cropper

πŸš€πŸžβœ‚οΈ Image cropper that can crop with static, dynamic crop behavior, can use customizable shapes, vectors, and other png files as mask to crop with various customizations
Kotlin
362
star
4

Compose-Image

πŸš€πŸžπŸ’ͺ Collection of Images, Modifiers, utility functions for Jetpack Compose to expand and enrich displaying, manipulating, scaling, resizing, zooming, and getting cropped ImageBitmap based on selection area
Kotlin
322
star
5

PropertyFindAR

🏘 πŸŽƒ Real Estate Sample App with RxJava3+Coroutines Flow, Dynamic Feature Modules, Dagger Hilt, Offline First, ConcatAdapter, Animations and tests for Room, Retrofit, useCase and ViewModels with TDD.
Kotlin
263
star
6

Compose-Colorful-Sliders

πŸš€πŸŒˆ 😍 Colorful Sliders written with Jetpack Compose that enliven default sliders with track and thumb dimensions, and gradient colors, borders, labels on top or at the bottom move with thumb and ColorfulIconSlider that can display emoji or any Composable as thumb
Kotlin
194
star
7

Compose-BeforeAfter

πŸš€πŸŒ†πŸ™ Display differences or animate progress between 2 images or Composables with overlay and customization options, zoom, pan gestures, and progress to observe properties for animating before-after progress
Kotlin
159
star
8

Toolbar-Samples

Toolbar Samples with TabLayout, CollapsingToolbarLayout and scroll flags, BottomNavigationView, BottomAppBarLayout and Window insets
Kotlin
153
star
9

Compose-Screenshot

πŸš€πŸ“Έ Screenshot Composables and convert to Bitmap or ImageBitmap on user action or periodically.
Kotlin
136
star
10

Compose-Drawing-App

βœοΈπŸš€ Drawing app written with Jetpack Compose Canvas. Draw using touch down, move and up events.Using array of paths to have erase, undo, or redo actions and set properties for path that will be drawn next separately.
Kotlin
97
star
11

Compose-Extended-Gestures

Counterpart of onTouchEvent, TouchDelegate, Transform gestures that notifies start, end, main pointer, pointers and option to consume PointerInputChange which defines whether other gestures should receive or not.
Kotlin
93
star
12

CoroutinesAndFlowTutorials

Series of Tutorials about Coroutines and Flow with Retrofit, Room, and Unit tests.
Kotlin
90
star
13

Compose-AnimatedList

πŸš€πŸ“±πŸ’–Animated LazyColumn/Row changes scale/color with animation and have a current selected item like a Pager. An elegant alternative for selecting from a list
Kotlin
85
star
14

Compose-Bubble

πŸš€πŸ’¬πŸ«§ Speech/Chat bubble written with Jetpack Compose and canvas with various properties such as arrow width, height, background color, shadow to create similar bubbles whatsapp, telegram or others have.
Kotlin
81
star
15

Posts-MVVM-DaggerHilt-Dynamic-Feature-RxJava3-Flow-Sample

Posts Api sample with Kotlin RxJava3/Coroutines Flow, Clean Architecture, Offline first/last with Room + Retrofit2, Dagger Hilt, Dynamic Feature Modules, Static Code Analysis, Gradle DSL, MockK+ MockWebServer with Test Driven Development including Api and Database tests
Kotlin
70
star
16

Compose-Color-Picker-Bundle

πŸš€πŸŒˆ 🎨 Collection of Color Pickers written with Jetpack Compose with solid Color or Gradient with type, tile mode, and color stops in HSL/HSV/RGB models with Colorful Sliders, displays, and many customization options.
Kotlin
69
star
17

Flexible-Chat-Box

Flexible chat row written with Jetpack Compose that positions message and message status based on number of message lines, message width and parent width. And resizable Subcomposelayout that remasures sibling composables to match their widths' to longest composable that matches quote and message width to max width.
Kotlin
55
star
18

Compose-ProgressIndicator

πŸš€πŸš₯β˜„οΈ Customizable progress indicators like on ios/mac/web, circle, scaled circle, gooey(sticky) indicators and dot indicators written with Jetpack Compose
Kotlin
52
star
19

Compose-Zoom

πŸš€πŸžπŸ” Zoom Modifiers, zoomable image and layouts with limit pan bounds, fling and moving back to valid bounds and callbacks that return current transformation or visible image section
Kotlin
51
star
20

Compose-RatingBar

πŸš€β­οΈπŸ‘ Rating bar to set fixed value or change rating using gestures with png or vector drawables and shimmer effect option
Kotlin
48
star
21

Compose-Extended-Colors

πŸš€πŸŒˆβ™Ύ Utility library that expands Compose Colors with Material Design2 colors, color swatches, Material Design 3 Tonal Palettes, color names, and utility functions to convert between HSL, HSV, RGB, HCT models and to HEX or from HEX
Kotlin
41
star
22

Compose-Color-Detector

πŸš€πŸŒˆπŸ” Detect colors from image or your screen after taking it's screenshot and get details as name, hex code, RGB, HSL. Written with Jetpack Compose and Material Design 3
Kotlin
28
star
23

Unit-Test-Tutorials

Series of Tutorials for Unit Testing in Java and Kotlin using JUnit4, JUnit5, Mockito, MockK and Test Driven Development
Kotlin
24
star
24

Android-DaggerHilt-DynamicFetureModule-Boilerplate

Boilerplate to create empty project with Dagger Hilt, Dynamic Feature modules, MVVM, RxJava, Coroutines with modularization
Kotlin
18
star
25

Dagger2-Tutorials

Series of tutorials for learning Dagger2, including dagger hilt, dynamic feature, dagger-android, dependent components, subcomponents and more
Kotlin
18
star
26

Compose-PagerIndicator

πŸš€πŸ“’πŸ“ Indicators for Horizontal or Vertical Pager with different orientation, color, size options and optional touch feature.
Kotlin
15
star
27

Kotlin-Tutorials

Series of Kotlin Tutorials
Kotlin
13
star
28

BubbleLayout

πŸ’¬ Chat/Speech bubble layout with various properties such as arrow width, height, background color, shadow to create similar bubbles whatsapp, telegram or others have.
Kotlin
11
star
29

MVVM-Tutorials

Series of tutorials about MVVM, data binding and Room and LiveData.
Java
10
star
30

Compose-Badge

βœοΈπŸ“Œ Dynamic Badge with customizable features as max number before displaying with +, color, shadow, border, corner radius, font properties and more written with Jetpack Compose. Displays numbers either in circle or rounded rectangle shape based on badge count and selected threshold to transform from circle to rounded rectangle.
Kotlin
10
star
31

SmartToolFactory

10
star
32

SAF-and-Scoped-Storage-Tutorials

Tutorials, utilities and playground for storing files with File, DocumentFile and Storage Access Framework
Java
9
star
33

BadgeTextView

βœ…βœοΈπŸ“Œ Badge TextView for Android to draw numbers on a TextView which is customizable and scalable. Displays numbers either as circle or rounded rectangle depending on badge count and selected threshold to transform from circle to rounded rectangle.
Kotlin
9
star
34

Compass-with-pixel-perfect

Elegant Compass View uses percentages instead of fixed values to draw components to have similar scales in both portrait and landscape orientations.
Kotlin
8
star
35

DataStructuresAndAlgorithmsPlayground

Playground fo data structures and algorithms
Kotlin
6
star
36

Transactional-Key-Value-Store

Transactional Key Value Store written with Jetpack Compose
Kotlin
5
star
37

My-Market-App

Android Challange 2019 - Market App with Kotlin, Room, Retrofit, Dagger, DataBinding, MVVM Clean Architecture with offline first
Kotlin
5
star
38

Static-Code-Analysis

Playground to test KtLint, Detekt, Git Hooks, Kotlin DSL
Kotlin
4
star
39

Github-Example

Github Example with MVVM, Dagger, RxJava, Retrofit, Navigation Components written with TDD
Kotlin
4
star
40

PhoneNumberCheck

PhoneUtilTest
Kotlin
3
star
41

The-Movie-DB-Example

Movie App Sample with MVVM clean arcitecture, Dagger2, Retrofit, RxJava2, DataBinding and Pagination
Kotlin
3
star
42

Room-Persistence-Library-Tutorials

Series of Tutorials about Room Persistance Library Tutorials
Java
2
star
43

RxJava-Tutorials

Tutorials about RxJava2
Kotlin
2
star
44

HopinStream

Hopin virtual event sample
Kotlin
2
star
45

Dynamic-Features-Tutorial

Series of tutorials about dynamic features and split install
Kotlin
2
star
46

Paging-Library-Tutorials

Paging Library Tutorials with only DB, only network and DB + Network
Kotlin
1
star
47

Bluetooth-LE-Smart-Tutorials

Tutorials about Bluetooth LE
Java
1
star
48

RxAndroid-Kotlin-Tutorials

RxJava Tutorials in Android Environment
Kotlin
1
star
49

RxJava-Style-LiveData-And-Flow-TestObserver

TestObserver class for LiveData to test multiple values like ViewState such as loading, and result states or multiple post and setValues
Kotlin
1
star
50

Answers-for-3-algorithm-questions

Kotlin
1
star
51

Flavors-and-Server-Driven-UI

Sample to create UI elements and enable/disable features based on flavors and Server driven updates. Create new UI or change position of elements based on parsing JSON filed downloaded by remote service such as Firebase or dedicated domain.
Kotlin
1
star