-
Notifications
You must be signed in to change notification settings - Fork 5
Quick Tutorials
- Initialize Navigator & navigate to start destination
- Navigate to a Fragment but remember the transaction
- Navigation with typed arguments
- Navigation with animation
- Navigation with single top instance or
popUpTo
- Navigate to a BottomSheet or Dialog Fragment
// initialize Navigator & with start destination as MyFragment.
val navigator = FragmentNavigator.with(this, savedStateInstance)
.initialize(findViewById(R.id.fragment_container), /*optional*/ Destination.of(MyFragment::class))
Furthermore, to navigate to other destination you can call navigator.navigateTo()
or navigator.show()
respectively.
Note: The host in which Navigator is set up must implement NavigationTransmittor
interface to propogate navigator
instance to its child fragments.
Why? Because Navigator does not add your fragment transaction to backstack
. You must explicitly specify this, so that on pressing back button (or navigating up) would take you back to the previous fragment.
navigator.navigate(MyFragment::class, FragmentNavigator.NavOptions(remember = true))
class MyFragment : ValueFragment(...) {
override fun onBackPressed() : Boolean {
if (condition-true) {
// do something to make condition false.
return true
}
return super.onBackPressed() // this call will remove the fragment.
}
}
Now when you call navigator.goBack()
from the host or when back button is pressed (assuming your setup is correct), FragmentNavigator
will first decide whether it is safe to remove this fragment from the backstack & then a call to onBackPressed()
will be invoked & based on the results the remove operation is performed.
- Create an argument class (typically a data class).
@Parcelize
data class MyArgs(
val name: String,
val age: Int
// any other types that can be parceled or serialized.
) : BaseArgs()
- Create the args & navigate to the destination fragment.
val args = MyArgs(
name = "John",
age = 20
)
navigator.navigate(MyFragment::class, FragmentNavigator.NavOptions(args = args))
- Parse the arguments in the destination fragment. The destination fragment must extend from
ValueFragment
.
class MyFragment : ValueFragment() {
override fun onViewCreated(...) {
...
if (hasKeyArgs<MyArgs>()) {
val args = getKeyArgs<MyArgs>()
println("Name: ${args.name}, Age: ${args.age}")
// clearArgs() // (optional) to consume args.
}
}
}
- There are some built-in animation as well as support for custom animation.
- This includes the traditional
anim
transition to the newanimator
one as well astransition
. However, if you don't want to create them, Navigator provides some default ones built on top of this. - Check
CircularTransform
custom animation to circular reveal fragments during a transaction.
// A simple fade transition.
val options = FragmentNavigator.NavOptions(
animation = Animation.Fade // or SlideInRight, SlideInLeft, etc.
)
// Supported "anim", "animator", or "transition"
val options = FragmentNavigator.NavOptions(
animation = Animation.Custom(
destinationEntering = R.anim.slide_from_right,
currentExiting = R.anim.fade
)
)
/**
* Shared element transition.
* - In xml set android:transitionName on the view eg: cardView (Fragment A)
* - (Fragment B) set android:transitionName on the view to share the transition eg: "heroCard".
*/
val options = FragmentNavigator.NavOptions(
animation = Animation.Shared(
elements = mapOf(
binding.cardView to "heroCard"
)
// optional enter/exit transition (defaults to fade).
)
)
// Navigate...
navigator.navigate(MyFragment::class, options)
-
If you've used Jetpack Navigation Component, there is a concept of single top instance or
popUpTo
when defining action. Basically, it helps you to clear backstack upto certain fragments. -
In case of
singleTopInstance
only one instance of such fragment are allowed in backstack. If there are multiple instance of this fragment the previous one will be removed & the current one will be placed. -
Clearing all previous backstack when navigating,
val options = FragmentNavigator.NavOptions(
historyOptions = HistoryOptions.ClearHistory
)
navigator.navigateTo(MyFragment::class, options)
- Maintain single instance of the fragment,
val options = FragmentNavigator.NavOptions(
historyOptions = HistoryOptions.SingleTopInstance
)
navigator.navigateTo(MyFragment::class, options)
- Clear history up to specific Fragment class or backstack name,
val options = FragmentNavigator.NavOptions(
historyOptions = HistoryOptions.PopToFragment(PreviousFragment::class, all = false) // or PopToBackStack
)
navigator.navigateTo(MyFragment::class, options)
- From the host
navigator.show(MyBottomSheetDialog::class, ...)
- From the child fragment
getParentNavigator().show(MyBottomSheetDialog::class, ...) // this uses parent's FragmentManager.
// or
getSimpleNavigator().show(MyBottomSheetDialog::class, ...) // this uses child's FragmentManager (recommended).
class MyBottomSheetDialog : BottomSheetDialogFragment() {
override fun onViewCreated(...) {
...
// optional arguments you can pass when calling navigator.show()
if (hasKeyArgs<MyArgs>()) {
val args = getKeyArgs<MyArgs>()
// process arguments..
}
}
}