Share
Embed
Youtube like BottomNavigation
kobito-kaba
July 01, 2022
Transcript
99 slides
-
making a new app - multi-module project - Jetpack Navigation
- BottomNavigationView -
making a new app - multi-module project - Jetpack Navigation
- BottomNavigationView → -
making a new app - multi-module project - Jetpack Navigation
- BottomNavigationView → -
Click QUIZ: When the Home menu is clicked, which screen
is displayed? 1. Welcome 2. About -
QUIZ: If you click the back key, which screen is
displayed? 1. Welcome 2. About Click -
QUIZ: If you click the back key, which screen is
displayed? 1. Welcome 2. About Click ? -
QUIZ: If you click the back key, which screen is
displayed? 1. Welcome 2. About Click ✕ -
Backstack SavedState menu A menu B ← When the back
key is pressed ← Can’t decide which should be restored -
Backstack SavedState menu A menu B ← New Instance Backstack
SavedState menu A menu B -
graph A1 B1 C1 D1 B2 B3 C2 C3 D2
D3 C4 C5 -
graph A1 B1 C1 D1 B2 B3 C2 C3 D2
D3 C4 C5 -
graph A1 B1 C1 D1 B2 B3 C2 C3 D2
D3 C4 C5 -
graph A1 B1 C1 D1 B2 B3 C2 C3 D2
D3 C4 C5 -
graph A1 B1 C1 D1 B2 B3 C2 C3 D2
D3 C4 C5 -
graph A1 B1 C1 D1 B2 B3 C2 C3 D2
D3 C4 C5 -
C1 C2 C3 D1 D2 Click menu D Click menu
C Then, the back key will navigate… ① ② ③ ④ ⑤ ⑥ C3 C3 C2 D2 D1 C3 C2 C1 C1 D2 D1 ⑥ ⑤ ④ ③ ② ① ② ③ ① ⑤ ④ -
class NavStack @Inject constructor(){ data class NavRecord(val screenId: Int, val
menuId: Int) private val selectedMenu = MutableStateFlow(R.id.none) fun push(screenId: Int, menuId: Int) { ... } fun pop(): NavRecord? { ... } fun peekAt(index: Int) : NavRecord? { ... } val size: Int get() { … } fun findByMenuId(menuId: Int): List<NavRecord> { ... } fun moveToTop(menuId: Int) { ... } fun removeAll(menuId: Int) { ... } } -
Navigate Switch menu Go Back if (currentMenuId == nextMenuId) {
stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments) } else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } -
Navigate case 1: within the same menu if (currentMenuId ==
nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments) } else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } -
if (currentMenuId == nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments)
} else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } Navigate case 2: across menus -
Navigate case 1: within the same menu if (currentMenuId ==
nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments) } else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } -
Navigate case 1: within the same menu if (currentMenuId ==
nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments) } else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } -
Navigate case 1: within the same menu if (currentMenuId ==
nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments) } else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } fragmentManager.commit { setReorderingAllowed(true) replace(requireNotNull(containerId), clazz.newInstance().apply { arguments = args }) addToBackStack(menuId.toString()) } -
Navigate case 1: within the same menu if (currentMenuId ==
nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments) } else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } fragmentManager.commit { setReorderingAllowed(true) replace(requireNotNull(containerId), clazz.newInstance().apply { arguments = args }) addToBackStack(menuId.toString()) } -
if (currentMenuId == nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments)
} else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } Navigate case 2: across menus -
if (currentMenuId == nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments)
} else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } Navigate case 2: across menus -
if (currentMenuId == nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments)
} else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } Navigate case 2: across menus -
if (currentMenuId == nextMenuId) { stack.push(screenId, currentMenuId) fragmentManager.replace(currentMenuId, nextScreen.clazz, arguments)
} else { stack.moveToTop(nextMenuId) stack.push(screenId, nextMenuId) fragmentManager.saveBackStack(currentMenuId.toString()) fragmentManager.restoreBackStack(nextMenuId.toString()) fragmentManager.replace(nextMenuId, nextScreen.clazz, arguments) } Navigate case 2: across menus -
Navigate Switch menu Go Back when { currentMenu.menuId == nextMenu.menuId
-> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 1: re-select menu when { currentMenu.menuId ==
nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 2: has no records when { currentMenu.menuId
== nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 3: click the same menu when {
currentMenu.menuId == nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 1: re-select menu when { currentMenu.menuId ==
nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 1: re-select menu when { currentMenu.menuId ==
nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 1: re-select menu when { currentMenu.menuId ==
nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 2: has no records when { currentMenu.menuId
== nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 2: has no records when { currentMenu.menuId
== nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 2: has no records when { currentMenu.menuId
== nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 3: click the same menu when {
currentMenu.menuId == nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 3: click the same menu when {
currentMenu.menuId == nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Switch Menu case 3: click the same menu when {
currentMenu.menuId == nextMenu.menuId -> { stack.removeAll(currentMenu.menuId) stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.clearBackStack(nextMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } stack.findByMenuId(nextMenu.menuId).isEmpty() -> { stack.push(startScreen.screenId, nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.replace(nextMenu.menuId, startScreen.clazz) } else -> { stack.moveToTop(nextMenu.menuId) fragmentManager.saveBackStack(currentMenu.menuId.toString()) fragmentManager.restoreBackStack(nextMenu.menuId.toString()) } } -
Navigate Switch menu Go Back when { destRecord == null
&& currentMenuId == graph.startMenuId -> { activity.finish() } destRecord == null -> { stack.push(startScreen.screenId, graph.startMenuId) fragmentManager.replace(graph.startMenuId, startScreen.clazz) } destRecord.menuId == currentMenuId -> { stack.pop() fragmentManager.popBackStack() } else -> { stack.pop() fragmentManager.popBackStack() fragmentManager.restoreBackStack(destRecord.menuId.toString()) } } -
Go Back case 1: can’t back at default menu when
{ destRecord == null && currentMenuId == graph.startMenuId -> { activity.finish() } destRecord == null -> { stack.push(startScreen.screenId, graph.startMenuId) fragmentManager.replace(graph.startMenuId, startScreen.clazz) } destRecord.menuId == currentMenuId -> { stack.pop() fragmentManager.popBackStack() } else -> { stack.pop() fragmentManager.popBackStack() fragmentManager.restoreBackStack(destRecord.menuId.toString()) } } -
Go Back case 2: can’t back at not default menu
when { destRecord == null && currentMenuId == graph.startMenuId -> { activity.finish() } destRecord == null -> { stack.push(startScreen.screenId, graph.startMenuId) fragmentManager.replace(graph.startMenuId, startScreen.clazz) } destRecord.menuId == currentMenuId -> { stack.pop() fragmentManager.popBackStack() } else -> { stack.pop() fragmentManager.popBackStack() fragmentManager.restoreBackStack(destRecord.menuId.toString()) } } -
Go Back case 3: navigate back inside the same menu
when { destRecord == null && currentMenuId == graph.startMenuId -> { activity.finish() } destRecord == null -> { stack.push(startScreen.screenId, graph.startMenuId) fragmentManager.replace(graph.startMenuId, startScreen.clazz) } destRecord.menuId == currentMenuId -> { stack.pop() fragmentManager.popBackStack() } else -> { stack.pop() fragmentManager.popBackStack() fragmentManager.restoreBackStack(destRecord.menuId.toString()) } } -
Go Back case 4: navigate back across menus when {
destRecord == null && currentMenuId == graph.startMenuId -> { activity.finish() } destRecord == null -> { stack.push(startScreen.screenId, graph.startMenuId) fragmentManager.replace(graph.startMenuId, startScreen.clazz) } destRecord.menuId == currentMenuId -> { stack.pop() fragmentManager.popBackStack() } else -> { stack.pop() fragmentManager.popBackStack() fragmentManager.restoreBackStack(destRecord.menuId.toString()) } } -
in Summary: - Fragment supports Multiple Backstack - BottomNavigationView works
weirdly - You can make it by yourself - I don’t want to make it -
in Summary: - Fragment supports Multiple Backstack - BottomNavigationView works
weirdly - You can make it by yourself - I don’t want to make it -
in Summary: - Fragment supports Multiple Backstack - BottomNavigationView works
weirdly - You can make it by yourself - I don’t want to make it -
in Summary: - Fragment supports Multiple Backstack - BottomNavigationView works
weirdly - You can make it by yourself - I don’t want to make it -
in Summary: - Fragment supports Multiple Backstack - BottomNavigationView works
weirdly - You can make it by yourself - I don’t want to make it