← 返回首页
Android-Extensions/navigation at develop · CrackerCat/Android-Extensions · GitHub
Skip to content

Navigation Menu

Toggle navigation
Sign in
Appearance settings
Search or jump to...

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Resetting focus

Latest commit

 

History

History
 
 
 develop
Top

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
View all files

README.md

Navigation

Independent Single Stacks Top Level MultiStack Navigation Nested MultiStack Navigation

Navigator

An interface for changing navigation destinations with Fragments.

StackNavigator

This class enforces rules about Fragments and the containers they are in a bid to make working with Fragments a lot easier. It's fairly opinionated, but it allows for very predictable Fragment interactions.

The basic crux of it's operation is that every Fragment added to a container must be added to the Fragment back stack, with a deterministic tag.

This way, if during navigation, a Fragment is requested to be shown, and an identical instance of that Fragment exists, that same instance is retrieved from the back stack and placed on top of the stack. The most convenient way to generate this tag, is by implementing the TagProvider interface, and delegating the stableTag property to the Fragment's arguments.

It also helps in preventing the same Fragment instance being shown twice, one after the other. If the same Fragment instance is asked to be shown, the request is simply ignored.

Another benefit is retrieving the current Fragment in the container, which is extremely useful for shared element transitions. This is because it allows for the isolation of FragmentTransition logic from the action that causes or starts them.

If for example clicking a view causes a FragmentTransaction with a shared element transition, the building of the FragmentTransaction for the Transition need not occur at the click site. In the case of an instance of TransactionModifier for example, a augmentTransaction(transaction: FragmentTransaction, incomingFragment: Fragment) API is exposed, allowing for the Fragment leaving to customize the FragmentTransaction for the Fragment about to come in, yielding a nice separation of concerns.

Interfaces:

  • TransactionModifier: A delegate for customizing the FragmentTransaction for Fragments shown and popped of the stack.

  • TagProvider: Typically implemented by the Fragment's themselves, this is an interface to provide a tag for each Fragment added to the stack.

It also provides:

  • A transactionModifier settable property reference to a TransactionModifier for augmenting the FragmentTransaction that shows each Fragment in the stack.

  • A convenience currentFragment property for accessing the current Fragment on top of the stack.

MultiStackNavigator

A class that allows for independent stacks of navigation, each backed by a StackNavigator instance. It is extremely useful for integrating multiple back stacks with a bottom navigation View. It does this using the child FragmentManager within instances of a StackFragment

It also provides:

  • A stackSelectedListener ((Int) -> Unit)? callback for when stack selection has changed, either directly or indirectly.

  • A stackTransactionModifier (FragmentTransaction.(Int) -> Unit)? for augmenting the FragmentTransaction that switches between the root StackFragment for each stack.

  • A transactionModifier (FragmentTransaction.(Fragment) -> Unit)? for augmenting the FragmentTransaction that shows child fragment instances within each StackFragment. This property is delegated internally to the StackNavigator for each StackFragment.

Example usage with BottomNavigationView:

class MainActivity : AppCompatActivity(R.layout.activity_main), StackNavigator.NavigationController { private val multiStackNavigator: MultiStackNavigator by multiStackNavigationController( R.id.content_container, intArrayOf(R.id.menu_core, R.id.menu_recyclerview, R.id.menu_communications) ) { id -> RouteFragment.newInstance(id).let { it to it.stableTag } } override val navigator: StackNavigator get() = multiStackNavigator.currentNavigator public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) findViewById<BottomNavigationView>(R.id.bottom_navigation).apply { multiStackNavigator.stackSelectedListener = { menu.findItem(it)?.isChecked = true } multiStackNavigator.transactionModifier = { incomingFragment -> val current = navigator.currentFragment if (current is StackNavigator.TransactionModifier) current.augmentTransaction(this, incomingFragment) else crossFade() } multiStackNavigator.stackTransactionModifier = { crossFade() } setOnApplyWindowInsetsListener { _: View?, windowInsets: WindowInsets? -> windowInsets } setOnNavigationItemSelectedListener { multiStackNavigator.show(it.itemId).let { true } } setOnNavigationItemReselectedListener { multiStackNavigator.currentNavigator.clear() } } onBackPressedDispatcher.addCallback(this) { if (!multiStackNavigator.pop()) finish() } } }

Please look at MainActivity in the sample app for more detail.

Each Navigator also supports a performConsecutively method that takes a coroutine scope, which lets you perform navigation operations one after the other as the FragmentManager is inherently asynchronous. This API is currently in alpha.

Footer

© 2026 GitHub, Inc.