Skip to content

Instantly share code, notes, and snippets.

@racka98
Last active June 20, 2022 20:44
Show Gist options
  • Save racka98/1f328e195e604fbdd43d8deeb17d096e to your computer and use it in GitHub Desktop.
Save racka98/1f328e195e604fbdd43d8deeb17d096e to your computer and use it in GitHub Desktop.
Bars Visibility utilities in Jetpack Compose. For cases when you want to hide a bottom navigation bar or top bar on a screen that does not need them.
/**
* The base properties and methods that each item will need.
* Just to make it easier to add more bars item that can need hiding.
* Eg. scroll bars, navigation rails, etc.
*/
@Stable
interface BarVisibilityState {
val isVisible: Boolean
fun hide()
fun show()
}
/**
* The default bar visibility state implementation.
* The class is marked with @Parcelize to make it easier to save it into a bundle so that it
* survives configuration changes. This uses kotlin-parcelize.
* Without parceling this class you would have to implement your own Saver to be used with
* rememberSaveable{ }.
* You could also use kotlinx-serialize (@Serializable) for using in Compose Multiplatform or
* just make your own Saver.
*/
@Parcelize
private class DefaultBarVisibilityState(
private val defaultVisibility: Boolean = true
) : BarVisibilityState, Parcelable {
private val _isVisible = mutableStateOf(defaultVisibility)
override val isVisible: Boolean by _isVisible
override fun hide() {
_isVisible.value = false
}
override fun show() {
_isVisible.value = true
}
private companion object : Parceler<DefaultBarVisibilityState> {
override fun create(parcel: Parcel): DefaultBarVisibilityState {
val isVisibleBool = BooleanArray(1)
parcel.readBooleanArray(isVisibleBool)
return DefaultBarVisibilityState(defaultVisibility = isVisibleBool[0])
}
override fun DefaultBarVisibilityState.write(parcel: Parcel, flags: Int) {
parcel.writeBooleanArray(booleanArrayOf(_isVisible.value))
}
}
}
/**
* The bars you want to change their visibility for.
* The items are of the interface [BarVisibilityState] for uniformity.
*/
@Stable
interface BarsVisibility {
val topBar: BarVisibilityState
val bottomBar: BarVisibilityState
// StatusBar and NavBar items are useful for triggering immersive mode
val statusBar: BarVisibilityState
val navigationBar: BarVisibilityState
}
/**
* A remember function for [BarsVisibility]. It survives configuration changes
* It should be used at the top level Composable or where the root NavHost is located
* and should be passed down to child Composables as needed.
*/
@Composable
fun rememberBarVisibility(): BarsVisibility {
val topBarState = rememberSaveable { DefaultBarVisibilityState() }
val bottomBarState = rememberSaveable { DefaultBarVisibilityState() }
val statusBarState = rememberSaveable { DefaultBarVisibilityState() }
val navigationBarState = rememberSaveable { DefaultBarVisibilityState() }
val barsVisibility: BarsVisibility by remember {
derivedStateOf {
object : BarsVisibility {
override val topBar: BarVisibilityState
get() = topBarState
override val bottomBar: BarVisibilityState
get() = bottomBarState
override val statusBar: BarVisibilityState
get() = statusBarState
override val navigationBar: BarVisibilityState
get() = navigationBarState
}
}
}
return barsVisibility
}
@Composable
fun App() {
val navController = rememberNavController()
val barsVisibility = rememberBarVisibility()
Scaffold(
modifier = Modifier,
bottomBar = {
AnimatedVisibility(
visible = barsVisibility.bottomBar.isVisible, // Bottom Bar visibility used here
enter = slideInVerticallyFadeReversed(),
exit = slideOutVerticallyFadeReversed()
) {
ReluctBottomNavBar(navController = navController)
}
}
) { innerPaddings ->
NavHost(
modifier = Modifier,
navController = navController,
startDestination = Graphs.DashboardDestinations.route,
route = Graphs.RootDestinations.route
) {
// Dashboard
dashboardNavGraph(
navController = navController,
barsVisibility = barsVisibility
)
// Screen 2
screen2NavGraph(
navController = navController,
barsVisibility = barsVisibility
)
// Screen 3
screen3NavGraph(
navController = navController,
barsVisibility = barsVisibility
)
}
}
}
// Let's say you want to hide the bottom bar when you open the Seach page found in screen3NavGraph
fun NavGraphBuilder.screen3NavGraph(
navController: NavHostController,
barsVisibility: BarsVisibility
) {
navigation(
route = "uniqueRoute",
startDestination = "uniqueRoute"
) {
// Tasks Page
composable(route = "uniqueRoute") {
barsVisibility.bottomBar.show() // Show the bottom bar when on Tasks page
TasksScreen(
onBackClicked = { navController.popBackStack() }
)
}
// Search Page
composable(route = "uniqueRoute") {
barsVisibility.bottomBar.hide() // Hide the bottom bar
TasksSearchScreen(
onNavigateToDetails = {
navController.navigate("detailsUniqueRoute")
},
onBackClicked = { navController.popBackStack() }
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment