diff --git a/app/src/main/java/com/skyyo/samples/extensions/NavControllerExtensions.kt b/app/src/main/java/com/skyyo/samples/extensions/NavControllerExtensions.kt index 75977b15..437a8bc5 100644 --- a/app/src/main/java/com/skyyo/samples/extensions/NavControllerExtensions.kt +++ b/app/src/main/java/com/skyyo/samples/extensions/NavControllerExtensions.kt @@ -14,8 +14,9 @@ import kotlinx.coroutines.launch fun NavigationDispatcher.getBackStackStateHandle( destinationId: Int?, + withBottomBar: Boolean? = null, observer: (SavedStateHandle) -> Unit -) = emit { +) = emit(withBottomBar) { val savedStateHandle = when (destinationId) { null -> it.previousBackStackEntry!!.savedStateHandle else -> it.getBackStackEntry(destinationId).savedStateHandle @@ -25,8 +26,9 @@ fun NavigationDispatcher.getBackStackStateHandle( fun NavigationDispatcher.getBackStackStateHandle( destinationId: String?, + withBottomBar: Boolean? = null, observer: (SavedStateHandle) -> Unit -) = emit { +) = emit(withBottomBar) { val savedStateHandle = when (destinationId) { null -> it.previousBackStackEntry!!.savedStateHandle else -> it.getBackStackEntry(destinationId).savedStateHandle @@ -45,8 +47,9 @@ fun NavigationDispatcher.observeNavigationResult( coroutineScope: CoroutineScope, key: String, initialValue: T, + withBottomBar: Boolean? = null, observer: (T) -> Unit, -) = emit { navController -> +) = emit(withBottomBar) { navController -> coroutineScope.launch { navController.currentBackStackEntry!!.savedStateHandle.getStateFlow(key, initialValue) .collect { @@ -69,8 +72,10 @@ fun NavController.navigateWithObject( val deepLinkMatch = graph.matchDeepLink(routeLink) if (deepLinkMatch != null && arguments != null) { val destination = deepLinkMatch.destination + val args = deepLinkMatch.matchingArgs ?: Bundle() + args.putAll(arguments) val id = destination.id - navigate(id, arguments, navOptions, extras) + navigate(id, args, navOptions, extras) } else { navigate(route, navOptions, extras) } @@ -79,12 +84,16 @@ fun NavController.navigateWithObject( // popUpToRoute - should always be the start destination of the bottomBar, not app fun NavController.navigateToRootDestination( route: String, + popInclusive: Boolean = false, popUpToRoute: String = Destination.Tab1.route ) { navigate(route) { - popUpTo(popUpToRoute) { saveState = true } launchSingleTop = true restoreState = true + popUpTo(popUpToRoute) { + saveState = true + inclusive = popInclusive + } } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogContacts/DogContactsViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogContacts/DogContactsViewModel.kt index a1b6fbc9..b99af13d 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogContacts/DogContactsViewModel.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogContacts/DogContactsViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel import com.skyyo.samples.application.Destination import com.skyyo.samples.extensions.getBackStackStateHandle import com.skyyo.samples.features.navigateWithResult.simple.dogFeed.DOG_STATUS_KEY +import com.skyyo.samples.features.navigationCores.bottomBar.WITH_BOTTOM_BAR_KEY import com.skyyo.samples.utils.NavigationDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -15,11 +16,12 @@ class DogContactsViewModel @Inject constructor( handle: SavedStateHandle, ) : ViewModel() { + private val withBottomBar = handle.get(WITH_BOTTOM_BAR_KEY) val dogId: String = requireNotNull(handle["dogId"]) @Suppress("MagicNumber") fun popToDogFeed() { - navigationDispatcher.emit { navController -> + navigationDispatcher.emit(withBottomBar) { navController -> val dogFeedScreenSavedStateHandle = navController.getBackStackStateHandle(Destination.DogFeed.route) dogFeedScreenSavedStateHandle[DOG_STATUS_KEY] = "adopted ${System.nanoTime() / 1000f}" navController.popBackStack(Destination.DogFeed.route, false) diff --git a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogDetails/DogDetailsViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogDetails/DogDetailsViewModel.kt index 20ed4f81..33cff910 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogDetails/DogDetailsViewModel.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogDetails/DogDetailsViewModel.kt @@ -1,8 +1,11 @@ package com.skyyo.samples.features.navigateWithResult.simple.dogDetails +import androidx.core.os.bundleOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import com.skyyo.samples.application.Destination +import com.skyyo.samples.extensions.navigateWithObject +import com.skyyo.samples.features.navigationCores.bottomBar.WITH_BOTTOM_BAR_KEY import com.skyyo.samples.utils.NavigationDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -13,9 +16,13 @@ class DogDetailsViewModel @Inject constructor( handle: SavedStateHandle, ) : ViewModel() { + private val withBottomBar = handle.get(WITH_BOTTOM_BAR_KEY) val dogId: String = requireNotNull(handle["dogId"]) - fun goContacts() = navigationDispatcher.emit { - it.navigate(Destination.DogContacts.createRoute("3333")) + fun goContacts() = navigationDispatcher.emit(withBottomBar) { + it.navigateWithObject( + route = Destination.DogContacts.createRoute("3333"), + arguments = bundleOf(WITH_BOTTOM_BAR_KEY to withBottomBar) + ) } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogFeed/DogFeedViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogFeed/DogFeedViewModel.kt index 210c02aa..a922b642 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogFeed/DogFeedViewModel.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/simple/dogFeed/DogFeedViewModel.kt @@ -1,10 +1,13 @@ package com.skyyo.samples.features.navigateWithResult.simple.dogFeed +import androidx.core.os.bundleOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.skyyo.samples.application.Destination +import com.skyyo.samples.extensions.navigateWithObject import com.skyyo.samples.extensions.observeNavigationResult +import com.skyyo.samples.features.navigationCores.bottomBar.WITH_BOTTOM_BAR_KEY import com.skyyo.samples.utils.NavigationDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -17,6 +20,7 @@ class DogFeedViewModel @Inject constructor( private val handle: SavedStateHandle, ) : ViewModel() { + private val withBottomBar = handle.get(WITH_BOTTOM_BAR_KEY) val dogStatus = handle.getStateFlow(DOG_STATUS_KEY, "") init { @@ -24,12 +28,18 @@ class DogFeedViewModel @Inject constructor( } private fun observeDogStatusResult() { - navigationDispatcher.observeNavigationResult(viewModelScope, DOG_STATUS_KEY, "") { - handle[DOG_STATUS_KEY] = it - } + navigationDispatcher.observeNavigationResult( + coroutineScope = viewModelScope, + key = DOG_STATUS_KEY, + initialValue = "", + withBottomBar = withBottomBar + ) { handle[DOG_STATUS_KEY] = it } } - fun goDogDetails() = navigationDispatcher.emit { - it.navigate(Destination.DogDetails.createRoute("2211")) + fun goDogDetails() = navigationDispatcher.emit(withBottomBar) { + it.navigateWithObject( + route = Destination.DogDetails.createRoute("2211"), + arguments = bundleOf(WITH_BOTTOM_BAR_KEY to withBottomBar) + ) } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catContacts/CatContactsViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catContacts/CatContactsViewModel.kt index 0a136e3b..ede6fa7e 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catContacts/CatContactsViewModel.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catContacts/CatContactsViewModel.kt @@ -6,6 +6,7 @@ import com.skyyo.samples.application.Destination import com.skyyo.samples.application.models.Dog import com.skyyo.samples.extensions.getBackStackStateHandle import com.skyyo.samples.features.navigateWithResult.withObject.catFeed.CAT_KEY +import com.skyyo.samples.features.navigationCores.bottomBar.WITH_BOTTOM_BAR_KEY import com.skyyo.samples.utils.NavigationDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -16,16 +17,17 @@ class CatContactsViewModel @Inject constructor( handle: SavedStateHandle, ) : ViewModel() { + private val withBottomBar = handle.get(WITH_BOTTOM_BAR_KEY) val cat: Dog = requireNotNull(handle["cat"]) private lateinit var catFeedHandle: SavedStateHandle init { - navigationDispatcher.getBackStackStateHandle(Destination.CatFeed.route) { + navigationDispatcher.getBackStackStateHandle(Destination.CatFeed.route, withBottomBar) { catFeedHandle = it } } - fun popToCatFeed() = navigationDispatcher.emit { + fun popToCatFeed() = navigationDispatcher.emit(withBottomBar) { catFeedHandle[CAT_KEY] = cat it.popBackStack(Destination.CatFeed.route, false) } diff --git a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catDetails/CatDetailsViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catDetails/CatDetailsViewModel.kt index 256c489a..63812bdd 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catDetails/CatDetailsViewModel.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catDetails/CatDetailsViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel import com.skyyo.samples.application.Destination import com.skyyo.samples.application.models.Dog import com.skyyo.samples.extensions.navigateWithObject +import com.skyyo.samples.features.navigationCores.bottomBar.WITH_BOTTOM_BAR_KEY import com.skyyo.samples.utils.NavigationDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -16,12 +17,13 @@ class CatDetailsViewModel @Inject constructor( private val handle: SavedStateHandle, ) : ViewModel() { + private val withBottomBar = handle.get(WITH_BOTTOM_BAR_KEY) val cat: Dog = requireNotNull(handle["cat"]) - fun goCatContacts() = navigationDispatcher.emit { + fun goCatContacts() = navigationDispatcher.emit(withBottomBar) { it.navigateWithObject( route = Destination.CatContacts.route, - arguments = bundleOf("cat" to cat) + arguments = bundleOf("cat" to cat, WITH_BOTTOM_BAR_KEY to withBottomBar) ) } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catFeed/CatFeedViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catFeed/CatFeedViewModel.kt index 4fcf7366..bc136e19 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catFeed/CatFeedViewModel.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigateWithResult/withObject/catFeed/CatFeedViewModel.kt @@ -8,6 +8,7 @@ import com.skyyo.samples.application.Destination import com.skyyo.samples.application.models.Dog import com.skyyo.samples.extensions.navigateWithObject import com.skyyo.samples.extensions.observeNavigationResult +import com.skyyo.samples.features.navigationCores.bottomBar.WITH_BOTTOM_BAR_KEY import com.skyyo.samples.utils.NavigationDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -20,6 +21,7 @@ class CatFeedViewModel @Inject constructor( private val handle: SavedStateHandle, ) : ViewModel() { + private val withBottomBar = handle.get(WITH_BOTTOM_BAR_KEY) // this is the result from CatContacts screen val cat = handle.getStateFlow(CAT_KEY, null) @@ -28,15 +30,21 @@ class CatFeedViewModel @Inject constructor( } private fun observeCatResult() { - navigationDispatcher.observeNavigationResult(viewModelScope, CAT_KEY, null) { - handle[CAT_KEY] = it - } + navigationDispatcher.observeNavigationResult( + coroutineScope = viewModelScope, + key = CAT_KEY, + initialValue = null, + withBottomBar = withBottomBar + ) { handle[CAT_KEY] = it } } - fun goCatDetails() = navigationDispatcher.emit { + fun goCatDetails() = navigationDispatcher.emit(withBottomBar) { it.navigateWithObject( route = Destination.CatDetails.route, - arguments = bundleOf(CAT_KEY to Dog(id = 99, name = "Kit")) + arguments = bundleOf( + CAT_KEY to Dog(id = 99, name = "Kit"), + WITH_BOTTOM_BAR_KEY to withBottomBar + ) ) } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/AnimatedBottomBar.kt b/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/AnimatedBottomBar.kt index 06d2297f..7715d7af 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/AnimatedBottomBar.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/AnimatedBottomBar.kt @@ -25,6 +25,7 @@ private const val EXPAND_ANIMATION_DURATION = 300 private const val COLLAPSE_ANIMATION_DURATION = 300 private const val FADE_IN_ANIMATION_DURATION = 350 private const val FADE_OUT_ANIMATION_DURATION = 300 +val BOTTOM_BAR_HEIGHT = 56.dp @Composable fun AnimatedBottomBar( @@ -54,13 +55,13 @@ fun AnimatedBottomBar( val enterSlide = remember { slideIn( animationSpec = tween(EXPAND_ANIMATION_DURATION), - initialOffset = { with(density) { IntOffset(0, 56.dp.roundToPx()) } } + initialOffset = { with(density) { IntOffset(0, BOTTOM_BAR_HEIGHT.roundToPx()) } } ) } val exitSlide = remember { slideOut( animationSpec = tween(COLLAPSE_ANIMATION_DURATION), - targetOffset = { with(density) { IntOffset(0, 56.dp.roundToPx()) } } + targetOffset = { with(density) { IntOffset(0, BOTTOM_BAR_HEIGHT.roundToPx()) } } ) } @@ -73,7 +74,7 @@ fun AnimatedBottomBar( BottomNavigation( backgroundColor = DarkGray, modifier = Modifier.windowInsetsBottomHeight( - WindowInsets.navigationBars.add(WindowInsets(bottom = 56.dp)) + WindowInsets.navigationBars.add(WindowInsets(bottom = BOTTOM_BAR_HEIGHT)) ) ) { items.forEachIndexed { index, screen -> diff --git a/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/BottomBarCore.kt b/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/BottomBarCore.kt index 620f8361..d11a6233 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/BottomBarCore.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/BottomBarCore.kt @@ -1,26 +1,30 @@ package com.skyyo.samples.features.navigationCores.bottomBar -import androidx.activity.compose.BackHandler -import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.* import androidx.compose.animation.core.tween -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.NavHostController +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.flowWithLifecycle +import androidx.navigation.* import com.google.accompanist.navigation.animation.AnimatedNavHost import com.google.accompanist.navigation.animation.composable import com.google.accompanist.systemuicontroller.SystemUiController import com.skyyo.samples.application.Destination import com.skyyo.samples.extensions.navigateToRootDestination +import com.skyyo.samples.features.navigateWithResult.simple.dogContacts.DogContactsScreen +import com.skyyo.samples.features.navigateWithResult.simple.dogDetails.DogDetailsScreen +import com.skyyo.samples.features.navigateWithResult.simple.dogFeed.DogFeedScreen +import com.skyyo.samples.features.navigateWithResult.withObject.catContacts.CatContactsScreen +import com.skyyo.samples.features.navigateWithResult.withObject.catDetails.CatDetailsScreen +import com.skyyo.samples.features.navigateWithResult.withObject.catFeed.CatFeedScreen import com.skyyo.samples.features.navigationCores.tab1.Tab1Screen import com.skyyo.samples.features.navigationCores.tab2.Tab2Screen import com.skyyo.samples.features.navigationCores.tab3.Tab3Screen @@ -32,6 +36,7 @@ fun BottomBarCore( startDestination: String, navController: NavHostController, systemUiController: SystemUiController, + viewModel: BottomBarViewModel = hiltViewModel() ) { val isBottomBarVisible = rememberSaveable { mutableStateOf(false) } val selectedTab = rememberSaveable { mutableStateOf(0) } @@ -53,6 +58,18 @@ fun BottomBarCore( navController.removeOnDestinationChangedListener(callback) } } + val lifecycleOwner = LocalLifecycleOwner.current + val navigationDispatcher = viewModel.navigationDispatcher + val navigationEvents = remember(navigationDispatcher.bottomBarNavControllerEvents, lifecycleOwner) { + navigationDispatcher.bottomBarNavControllerEvents.flowWithLifecycle( + lifecycleOwner.lifecycle, + Lifecycle.State.STARTED + ) + } + + LaunchedEffect(Unit) { + navigationEvents.collect { event -> event(navController) } + } Box { AnimatedNavHost( @@ -60,24 +77,17 @@ fun BottomBarCore( startDestination = startDestination, enterTransition = { fadeIn(animationSpec = tween(durationMillis = 350)) }, exitTransition = { fadeOut(animationSpec = tween(durationMillis = 350)) }, - modifier = Modifier.padding(0.dp) + modifier = Modifier.padding(bottom = if (isBottomBarVisible.value) BOTTOM_BAR_HEIGHT else 0.dp) ) { - composable(Destination.Tab1.route) { Tab1Screen() } - composable(Destination.Tab2.route) { - BackHandler(onBack = { - selectedTab.value = 0 - navController.navigateToRootDestination(Destination.Tab1.route) - }) - Tab2Screen() - } - composable(Destination.Tab3.route) { - BackHandler(onBack = { - selectedTab.value = 0 - navController.navigateToRootDestination(Destination.Tab1.route) - }) - Tab3Screen() - } + composable(Destination.Tab2.route) { Tab2Screen(withBottomBar = true) } + composable(Destination.Tab3.route) { Tab3Screen(withBottomBar = true) } + composable(Destination.DogFeed.route) { DogFeedScreen() } + composable(Destination.DogDetails.route) { DogDetailsScreen() } + composable(Destination.DogContacts.route) { DogContactsScreen() } + composable(Destination.CatFeed.route) { CatFeedScreen() } + composable(Destination.CatDetails.route) { CatDetailsScreen() } + composable(Destination.CatContacts.route) { CatContactsScreen() } } AnimatedBottomBar( Modifier.align(Alignment.BottomCenter), @@ -87,8 +97,13 @@ fun BottomBarCore( ) { index, route -> // this means we're already on the selected tab if (index == selectedTab.value) return@AnimatedBottomBar + val selectedRoute = bottomBarScreens[selectedTab.value] selectedTab.value = index - navController.navigateToRootDestination(route) + navController.navigateToRootDestination( + route = route, + popInclusive = true, + popUpToRoute = selectedRoute.route + ) } } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/BottomBarViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/BottomBarViewModel.kt new file mode 100644 index 00000000..bc685f3a --- /dev/null +++ b/app/src/main/java/com/skyyo/samples/features/navigationCores/bottomBar/BottomBarViewModel.kt @@ -0,0 +1,13 @@ +package com.skyyo.samples.features.navigationCores.bottomBar + +import androidx.lifecycle.ViewModel +import com.skyyo.samples.utils.NavigationDispatcher +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +const val WITH_BOTTOM_BAR_KEY = "withBottomBar" + +@HiltViewModel +class BottomBarViewModel @Inject constructor( + val navigationDispatcher: NavigationDispatcher +) : ViewModel() diff --git a/app/src/main/java/com/skyyo/samples/features/navigationCores/drawer/DrawerCore.kt b/app/src/main/java/com/skyyo/samples/features/navigationCores/drawer/DrawerCore.kt index b9cb145f..c27ac563 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigationCores/drawer/DrawerCore.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigationCores/drawer/DrawerCore.kt @@ -117,14 +117,14 @@ fun DrawerCore( selectedTab.value = 0 navController.navigateToRootDestination(Destination.Tab1.route) }) - Tab2Screen() + Tab2Screen(withBottomBar = false) } composable(Destination.Tab3.route) { BackHandler(onBack = { selectedTab.value = 0 navController.navigateToRootDestination(Destination.Tab1.route) }) - Tab3Screen() + Tab3Screen(withBottomBar = false) } } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigationCores/tab2/Tab2Screen.kt b/app/src/main/java/com/skyyo/samples/features/navigationCores/tab2/Tab2Screen.kt index 9bb33a03..624cebcb 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigationCores/tab2/Tab2Screen.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigationCores/tab2/Tab2Screen.kt @@ -1,21 +1,36 @@ package com.skyyo.samples.features.navigationCores.tab2 import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel @Composable -fun Tab2Screen() { +fun Tab2Screen(withBottomBar: Boolean, viewModel: Tab2ViewModel = hiltViewModel()) { Box( modifier = Modifier .fillMaxSize() .background(Color.Red) ) { Text(text = "tab 2", Modifier.align(Alignment.Center)) + if (withBottomBar) { + Text( + text = "go dog feed", + modifier = Modifier + .align(Alignment.BottomCenter) + .navigationBarsPadding() + .padding(bottom = 10.dp) + .clickable(onClick = viewModel::goDogFeed) + ) + } } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigationCores/tab2/Tab2ViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigationCores/tab2/Tab2ViewModel.kt index 6c61bfc8..96003f81 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigationCores/tab2/Tab2ViewModel.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigationCores/tab2/Tab2ViewModel.kt @@ -1,7 +1,11 @@ package com.skyyo.samples.features.navigationCores.tab2 +import androidx.core.os.bundleOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel +import com.skyyo.samples.application.Destination +import com.skyyo.samples.extensions.navigateWithObject +import com.skyyo.samples.features.navigationCores.bottomBar.WITH_BOTTOM_BAR_KEY import com.skyyo.samples.utils.NavigationDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -10,4 +14,11 @@ import javax.inject.Inject class Tab2ViewModel @Inject constructor( private val navigationDispatcher: NavigationDispatcher, private val handle: SavedStateHandle, -) : ViewModel() +) : ViewModel() { + fun goDogFeed() = navigationDispatcher.bottomBarNavControllerEmit { + it.navigateWithObject( + route = Destination.DogFeed.route, + arguments = bundleOf(WITH_BOTTOM_BAR_KEY to true) + ) + } +} diff --git a/app/src/main/java/com/skyyo/samples/features/navigationCores/tab3/Tab3Screen.kt b/app/src/main/java/com/skyyo/samples/features/navigationCores/tab3/Tab3Screen.kt index c7718ca2..e50fba0d 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigationCores/tab3/Tab3Screen.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigationCores/tab3/Tab3Screen.kt @@ -1,21 +1,36 @@ package com.skyyo.samples.features.navigationCores.tab3 import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel @Composable -fun Tab3Screen() { +fun Tab3Screen(withBottomBar: Boolean, viewModel: Tab3ViewModel = hiltViewModel()) { Box( modifier = Modifier .fillMaxSize() .background(Color.Gray) ) { Text(text = "tab 3", Modifier.align(Alignment.Center)) + if (withBottomBar) { + Text( + text = "go cat feed", + modifier = Modifier + .align(Alignment.BottomCenter) + .navigationBarsPadding() + .padding(bottom = 10.dp) + .clickable(onClick = viewModel::goCatFeed) + ) + } } } diff --git a/app/src/main/java/com/skyyo/samples/features/navigationCores/tab3/Tab3ViewModel.kt b/app/src/main/java/com/skyyo/samples/features/navigationCores/tab3/Tab3ViewModel.kt index fcf259e5..ebf15599 100644 --- a/app/src/main/java/com/skyyo/samples/features/navigationCores/tab3/Tab3ViewModel.kt +++ b/app/src/main/java/com/skyyo/samples/features/navigationCores/tab3/Tab3ViewModel.kt @@ -1,7 +1,11 @@ package com.skyyo.samples.features.navigationCores.tab3 +import androidx.core.os.bundleOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel +import com.skyyo.samples.application.Destination +import com.skyyo.samples.extensions.navigateWithObject +import com.skyyo.samples.features.navigationCores.bottomBar.WITH_BOTTOM_BAR_KEY import com.skyyo.samples.utils.NavigationDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -10,4 +14,11 @@ import javax.inject.Inject class Tab3ViewModel @Inject constructor( private val navigationDispatcher: NavigationDispatcher, private val handle: SavedStateHandle, -) : ViewModel() +) : ViewModel() { + fun goCatFeed() = navigationDispatcher.bottomBarNavControllerEmit { + it.navigateWithObject( + route = Destination.CatFeed.route, + arguments = bundleOf(WITH_BOTTOM_BAR_KEY to true) + ) + } +} diff --git a/app/src/main/java/com/skyyo/samples/utils/NavigationDispatcher.kt b/app/src/main/java/com/skyyo/samples/utils/NavigationDispatcher.kt index 24c1bebb..527103f0 100644 --- a/app/src/main/java/com/skyyo/samples/utils/NavigationDispatcher.kt +++ b/app/src/main/java/com/skyyo/samples/utils/NavigationDispatcher.kt @@ -3,6 +3,7 @@ package com.skyyo.samples.utils import androidx.navigation.NavController import dagger.hilt.android.scopes.ActivityRetainedScoped import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.ChannelResult import kotlinx.coroutines.flow.receiveAsFlow import javax.inject.Inject @@ -14,4 +15,15 @@ class NavigationDispatcher @Inject constructor() { val emitter = _emitter.receiveAsFlow() fun emit(navigationEvent: NavigationEvent) = _emitter.trySend(navigationEvent) + + private val _bottomBarNavControllerEmitter = Channel(Channel.UNLIMITED) + fun bottomBarNavControllerEmit(navigationEvent: NavigationEvent): ChannelResult { + return _bottomBarNavControllerEmitter.trySend(navigationEvent) + } + val bottomBarNavControllerEvents = _bottomBarNavControllerEmitter.receiveAsFlow() + + fun emit(withBottomBar: Boolean?, navigationEvent: NavigationEvent) = when (withBottomBar) { + true -> bottomBarNavControllerEmit(navigationEvent) + else -> emit(navigationEvent) + } }