I have a simple proof of concept app that contains only 2 fragments: MainFragment
and RepositoryFragment
and 1 activity: MainActivity
Here's my nav_graph
<?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/nav_graph"
app:startDestination="@id/id_main">
<fragment
android:id="@+id/id_main"
android:name="com.repofetcher.main.view.MainFragment"
android:label="@string/app_name"
tools:layout="@layout/main_fragment">
<action
android:id="@+id/action_mainfragment_to_repositoryfragment"
app:destination="@id/id_repo"
app:popUpTo="@id/id_main"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="@+id/id_repo"
android:name="com.repofetcher.repo.view.RepositoryFragment"
android:label="{arg_repo_name}"
tools:layout="@layout/repository_fragment">
<argument
android:name="arg_repo_name"
app:argType="string"
android:defaultValue="@null"
app:nullable="true" />
</fragment>
</navigation>
MainActivity:
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
(application as RepoFetcherApplication).appComponent.mainComponent().create().inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
navController = findNavController(R.id.nav_host_fragment)
setupActionBarWithNavController(navController)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp() || super.onSupportNavigateUp()
}
Main activity's layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".main.view.MainActivity">
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
This is the part that navigates from MainFragment
to RepositoryFragment
private fun navToRepositoryFragment(name: String) {
findNavController().navigate(MainFragmentDirections.actionMainfragmentToRepositoryfragment(argRepoName = name))
}
RepositoryFragment:
override fun onCreate(savedInstanceState: Bundle?) {
(requireActivity().application as RepoFetcherApplication).appComponent.repoComponent().create().inject(this)
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
dataBinding = DataBindingUtil.inflate(inflater, R.layout.repository_fragment, container, false)
dataBinding.lifecycleOwner = this
viewModel = ViewModelProvider(this, viewModelProviderFactory).get(RepositoryViewModel::class.java)
dataBinding.viewModel = viewModel
return dataBinding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel.getRepository(args.argRepoName)
}
Ideally, I would like to achieve these navigations:
navigating from MainFragment
to RepositoryFragment
, then by clicking either the back button on the Toolbar
or on the device, it should navigate back to the MainFragment
.
However in my case, only the back button on the toolbar will work as intended. The back button on the device will directly quit the app.
I wonder what I'm missing in the code?
One of the real problem behind this question is I used livedata for a single event (to handle the click event in order to navigate to RepositoryFragment
).
So after taking a look at this article : https://proandroiddev.com/livedata-with-single-events-2395dea972a8
with solution @GabrieleMariotti provided and got the problem solved.
I would like to thank @GabrieleMariotti who helped me with great patient.
Remove the app:popUpTo="@id/id_main"
and app:popUpToInclusive="true
in your action
:
<action
android:id="@+id/action_mainfragment_to_repositoryfragment"
app:destination="@id/nav_gallery"
/>
In your onCreate
method use:
appBarConfiguration = AppBarConfiguration(navController.graph)
setupActionBarWithNavController(navController, appBarConfiguration)
and in your onSupportNavigateUp
method:
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}