Add (not replace) fragment with navigation architecture component Add (not replace) fragment with navigation architecture component android android

Add (not replace) fragment with navigation architecture component


Android navigation component just replace but you want to add fragment instead of replace like dialog you can use this but need to min. "Version 2.1.0" for navigation component.

Solution

and you can see "Dialog destinations"


I faced the same problem, while waiting on add and other options for fragment transactions I implemented this work around to preserve the state when hitting back.

I just added a check if the binding is present then I just restore the previous state, the same with the networking call, I added a check if the data is present in view model then don't do the network refetching. After testing it works as expected.

EDIT: For the recycler view I believe it will automatically return to the same sate the list was before you navigated from the fragment but storing the position in the onSavedInstanceSate is also possible

  private lateinit var binding: FragmentSearchResultsBinding  override fun onCreateView(        inflater: LayoutInflater,        container: ViewGroup?,        savedInstanceState: Bundle?    ): View? {        viewModel =            ViewModelProviders.of(this, mViewModelFactory).get(SearchResultsViewModel::class.java)        return if (::binding.isInitialized) {            binding.root        } else {            binding = DataBindingUtil.inflate(inflater, R.layout.fragment_search_results, container, false)            with(binding) {               //some stuff                root            }        }}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        //reload only if search results are empty        if (viewModel.searchResults.isEmpty()) {           args.searchKey.let {                binding.toolbarHome.title = it                viewModel.onSearchResultRequest(it)            }        }    }


You have to override NavHostFragment's createFragmentNavigator method and return YourFragmentNavigator.

YourFragmentNavigator must override FragmentNavigator's navigate method.

Copy and paste FragmentNavigator's navigate method to your YourFragmentNavigator.

In navigate method, change the line ft.replace(mContainerId, frag); with

if (fragmentManager.fragments.size <= 0) {    ft.replace(containerId, frag)} else {    ft.hide(fragmentManager.fragments[fragmentManager.fragments.size - 1])    ft.add(containerId, frag)}

The solution will look like this:

class YourNavHostFragment : NavHostFragment() {override fun createFragmentNavigator(): Navigator<...> {    return YourFragmentNavigator(...)}}

....

class YourFragmentNavigator(...) : FragmentNavigator(...) {override fun navigate(...){    ....    if (fragmentManager.fragments.size <= 0) {        ft.replace(containerId, frag)    } else {        ft.hide(fragmentManager.fragments[fragmentManager.fragments.size - 1])        ft.add(containerId, frag)     }     ....}}

in your xml use YourNavHostFragment.