Skip to content
This repository was archived by the owner on Jan 10, 2025. It is now read-only.

[NavigationAdvancedSample] Adds optional case for item reselected #578

Merged
merged 1 commit into from
Mar 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,24 @@ class BottomNavigationTest {
assertDeeperThirdScreen()
}

@Test
fun bottomNavView_itemReselected_goesBackToStart() {
openThirdScreen()

assertThirdScreen()

onView(withContentDescription(R.string.sign_up))
.perform(click())

assertDeeperThirdScreen()

// Reselect the current item
openThirdScreen()

// Verify that it popped the back stack until the start destination.
assertThirdScreen()
}

private fun assertSecondScreen() {
onView(allOf(withText(R.string.title_list), isDescendantOfA(withId(R.id.action_bar))))
.check(matches(isDisplayed()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ fun BottomNavigationView.setupWithNavController(
val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId]
var isOnFirstFragment = selectedItemTag == firstFragmentTag

// For the navigation item that is selected...
// When a navigation item is selected
setOnNavigationItemSelectedListener { item ->
// Don't do anything if the state is state has already been saved.
if (fragmentManager.isStateSaved) {
Expand Down Expand Up @@ -131,22 +131,11 @@ fun BottomNavigationView.setupWithNavController(
}
}

// handle deep link
navGraphIds.forEachIndexed { index, navGraphId ->
val fragmentTag = getFragmentTag(index)
// Optional: on item reselected, pop back stack to the destination of the graph
setupItemReselected(graphIdToTagMap, fragmentManager)

// Find or create the Navigation host fragment
val navHostFragment = obtainNavHostFragment(
fragmentManager,
fragmentTag,
navGraphId,
containerId
)
// Handle Intent
if (navHostFragment.navController.handleDeepLink(intent)) {
this.selectedItemId = navHostFragment.navController.graph.id
}
}
// Handle deep link
setupDeepLinks(navGraphIds, fragmentManager, containerId, intent)

// Finally, ensure that we update our BottomNavigationView when the back stack changes
fragmentManager.addOnBackStackChangedListener {
Expand All @@ -165,6 +154,45 @@ fun BottomNavigationView.setupWithNavController(
return selectedNavController
}

private fun BottomNavigationView.setupDeepLinks(
navGraphIds: List<Int>,
fragmentManager: FragmentManager,
containerId: Int,
intent: Intent
) {
navGraphIds.forEachIndexed { index, navGraphId ->
val fragmentTag = getFragmentTag(index)

// Find or create the Navigation host fragment
val navHostFragment = obtainNavHostFragment(
fragmentManager,
fragmentTag,
navGraphId,
containerId
)
// Handle Intent
if (navHostFragment.navController.handleDeepLink(intent)) {
this.selectedItemId = navHostFragment.navController.graph.id
}
}
}

private fun BottomNavigationView.setupItemReselected(
graphIdToTagMap: SparseArray<String>,
fragmentManager: FragmentManager
) {
setOnNavigationItemReselectedListener { item ->
val newlySelectedItemTag = graphIdToTagMap[item.itemId]
val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag)
as NavHostFragment
val navController = selectedFragment.navController
// Pop the back stack to the start destination of the current navController graph
navController.popBackStack(
navController.graph.startDestination, false
)
}
}

private fun detachNavHostFragment(
fragmentManager: FragmentManager,
navHostFragment: NavHostFragment
Expand Down