I have an Activity, where I have a fragment, in which I have referenced a Navigation Graph component:
activity XML:
<LinearLayout 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"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.fragment.app.FragmentContainerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_fragment"
app:defaultNavHost="true"
android:name="androidx.navigation.fragment.NavHostFragment"
android:id="@+id/fragment_main" />
</LinearLayout>
Navigation graph:
<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_fragment"
app:startDestination="@id/countryPickerFragment">
<fragment
android:id="@+id/countryPickerFragment"
android:name="me.sparker0i.ottcontent.view.composer.countrypicker.CountryPickerFragment"
android:label="Pick a Country"
tools:layout="@layout/fragment_country_picker">
<action android:id="@+id/countryPickerFragmentToPlatformPickerFragment"
app:destination="@+id/platformPickerFragment">
<argument
android:name="countryValue"
app:argType="string" />
</action>
</fragment>
<fragment
android:id="@+id/platformPickerFragment"
android:name="me.sparker0i.ottcontent.view.composer.platformpicker.PlatformPickerFragment"
android:label="Pick a Platform"
tools:layout="@layout/fragment_platform_picker">
<argument
android:name="countryValue"
app:argType="string" />
</fragment>
</navigation>
Activity Code:
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment_main) as NavHostFragment
navController = navHostFragment.navController
NavigationUI.setupActionBarWithNavController(this, navController)
}
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(navController, null)
}
}
In the first fragment that opens up (CountryPickerFragment
), I have code which observes a value from a MutableLiveData
inside a ViewModel
. When the value is observed, it opens up the 2nd fragment, navigated using the Navigation Library. The relevant code for the CountryPickerFragment
is below:
class CountryPickerFragment : Fragment(), KodeinAware, CoroutineScope {
override val kodein by closestKodein()
private lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
job = Job()
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
private var mutableCountries = MutableLiveData<List<Country>>()
private val viewModelFactory: ContentViewModelFactory by instance()
private lateinit var viewModel: ContentViewModel
private lateinit var selectionTracker: SelectionTracker<Long?>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_country_picker, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProvider(this, viewModelFactory).get(ContentViewModel::class.java)
viewModel.countryValue.observeForever{value ->
val action = CountryPickerFragmentDirections.countryPickerFragmentToPlatformPickerFragment(value)
requireView().findNavController().navigate(action)
}
}
}
Here's the second fragment as well:
class PlatformPickerFragment : Fragment(), KodeinAware, CoroutineScope {
override val kodein by closestKodein()
private lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
job = Job()
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
val args: PlatformPickerFragmentArgs by navArgs()
private val viewModelFactory: ContentViewModelFactory by instance()
private lateinit var viewModel: ContentViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_platform_picker, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProvider(this, viewModelFactory).get(ContentViewModel::class.java)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val countryValue = args.countryValue
Log.i("Country Value", countryValue)
}
}
While this piece of code does open up the Second fragment within the same activity and also shows up the Country Value
inside Logcat, it also brings a Back button on the Action Bar. When I try to press that back button, it does not go back to the previous fragment, instead it puts up yet another Country Value
inside the Logcat. Pressing the back button on the phone's navigation bar also does the same.
How do I go back to the previous fragment (CountryPickerFragment
) from the newly spawned fragment (PlatformPickerFragment
)?
PS. If anyone wants to have a look at the code, you may go here