Skip to content

Instantly share code, notes, and snippets.

@freaksgit
Last active April 16, 2019 14:06
Show Gist options
  • Save freaksgit/79a9b2cc45ee3b58e0810fcef18b944f to your computer and use it in GitHub Desktop.
Save freaksgit/79a9b2cc45ee3b58e0810fcef18b944f to your computer and use it in GitHub Desktop.
Navigation component keep state navigator sample
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/bottomNav"
android:id="@+id/nav_host_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNav"
android:layout_width="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/nav_host_fragment"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:menu="@menu/menu_navigation"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nav_host_fragment1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/navigation1"
app:defaultNavHost="true"/>
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nav_host_fragment2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/navigation2"
app:defaultNavHost="true"/>
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.FragmentManager
import androidx.navigation.NavDestination
import androidx.navigation.NavOptions
import androidx.navigation.Navigator
import androidx.navigation.fragment.FragmentNavigator
@Navigator.Name("keep_state_fragment") // `keep_state_fragment` is used in navigation xml
class KeepStateNavigator(
private val context: Context,
private val manager: FragmentManager, // Should pass childFragmentManager.
private val containerId: Int
) : FragmentNavigator(context, manager, containerId) {
override fun navigate(
destination: Destination,
args: Bundle?,
navOptions: NavOptions?,
navigatorExtras: Navigator.Extras?
): NavDestination? {
val tag = destination.id.toString()
val transaction = manager.beginTransaction()
val currentFragment = manager.primaryNavigationFragment
if (currentFragment != null) {
transaction.detach(currentFragment)
}
var fragment = manager.findFragmentByTag(tag)
if (fragment == null) {
val className = destination.className
fragment = instantiateFragment(context, manager, className, args)
transaction.add(containerId, fragment, tag)
} else {
transaction.attach(fragment)
}
transaction.setPrimaryNavigationFragment(fragment)
transaction.setReorderingAllowed(true)
transaction.commit()
return null
}
}
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.navigation.plusAssign
import androidx.navigation.ui.NavigationUI
import navigation.KeepStateNavigator
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val navController: NavController
get() {
return Navigation.findNavController(this, R.id.nav_host_fragment)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupNavigation()
}
private fun setupNavigation() {
supportFragmentManager.findFragmentById(R.id.nav_host_fragment)?.let { navHostFragment ->
// setup custom navigator
val navigator = KeepStateNavigator(this, navHostFragment.childFragmentManager, R.id.nav_host_fragment)
navController.navigatorProvider += navigator
// set navigation graph
navController.setGraph(R.navigation.mobile_navigation)
NavigationUI.setupWithNavController(bottomNav, navController)
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/flowFragment1"
android:icon="@drawable/ic_airplay_black_24dp"
android:title="1"/>
<item android:id="@+id/flowFragment2"
android:icon="@drawable/ic_subscriptions_black_24dp"
android:title="2"/>
</menu>
<?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/mobile_navigation" app:startDestination="@id/flowFragment1">
<keep_state_fragment android:id="@+id/flowFragment1"
android:name="FlowFragment1"
android:label="FlowFragment1"
tools:layout="@layout/fragment1_flow"/>
<keep_state_fragment android:id="@+id/flowFragment2"
android:name="flowFragment2"
android:label="flowFragment2"
tools:layout="@layout/fragment2_flow"/>
</navigation>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment