Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jshvarts committed Nov 8, 2022
1 parent 5be9a9b commit e2c7769
Show file tree
Hide file tree
Showing 16 changed files with 372 additions and 133 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Jetpack Compose: Conditionally show BottomBar

Demonstrates how to conditionally show BottomBar with bottom navigation in Jetpack Compose

![demo](conditionalBottomNav.gif)
18 changes: 6 additions & 12 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,13 @@ android {

dependencies {

implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation 'androidx.activity:activity-compose:1.6.1'
implementation "androidx.compose.ui:ui:$compose_ui_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
implementation 'androidx.compose.material:material:1.1.1'
implementation 'androidx.compose.material:material:1.3.0'
implementation "com.google.accompanist:accompanist-systemuicontroller:0.27.0"

implementation("androidx.navigation:navigation-compose:2.4.0-beta02")
implementation("androidx.compose.ui:ui-util:1.3.0")
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"
implementation("androidx.navigation:navigation-compose:2.6.0-alpha03")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.jshvarts.conditionalbottomnav

object HomeItemRepo {
fun getItems(): List<HomeItem> = getHomeItemList()
fun getItem(itemId: Int) = getItems().find { it.id == itemId }!!
}

private fun getHomeItemList(): List<HomeItem> {
return MutableList(20) { index ->
val cardNumber = index + 1
HomeItem(cardNumber, "Item $cardNumber")
}
}

data class HomeItem(
val id: Int,
val text: String
)
170 changes: 53 additions & 117 deletions app/src/main/java/com/jshvarts/conditionalbottomnav/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,49 @@ package com.jshvarts.conditionalbottomnav
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AccountCircle
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.Search
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.Lifecycle
import androidx.navigation.*
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavDestination
import androidx.navigation.NavGraph
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.navigation
import androidx.navigation.compose.rememberNavController
import com.jshvarts.conditionalbottomnav.MainDestinations.GAME_CARD_DETAIL_ROUTE
import com.jshvarts.conditionalbottomnav.MainDestinations.HOME_ROUTE
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.jshvarts.conditionalbottomnav.navigation.BottomBarTab
import com.jshvarts.conditionalbottomnav.navigation.HOME_GRAPH
import com.jshvarts.conditionalbottomnav.navigation.HomeDestinations.HOME_ITEM_ROUTE
import com.jshvarts.conditionalbottomnav.navigation.navGraph
import com.jshvarts.conditionalbottomnav.ui.theme.ConditionalBottomNavTheme

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ConditionalBottomNavTheme {
val systemUiController = rememberSystemUiController()
val useDarkIcons = !isSystemInDarkTheme()
DisposableEffect(systemUiController, useDarkIcons) {
systemUiController.setStatusBarColor(
color = Color.White,
darkIcons = useDarkIcons
)
onDispose {}
}

// A surface container using the 'background' color from the theme
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
App()
Expand All @@ -58,12 +69,16 @@ fun App() {
)
}
}
) {
) { innerPaddingModifier ->
NavHost(
navController = appState.navController,
startDestination = MainDestinations.HOME_ROUTE
startDestination = HOME_GRAPH,
modifier = Modifier.padding(innerPaddingModifier)
) {
navGraph(appState.navController)
navGraph(
onHomeItemSelected = appState::navigateToHomeItemDetail,
upPress = appState::upPress
)
}
}
}
Expand All @@ -77,48 +92,6 @@ fun rememberAppState(
AppState(navController)
}

fun NavGraphBuilder.navGraph(navController: NavController) {
navigation(
route = HOME_ROUTE,
startDestination = BottomBarTab.CATALOG.route
) {
addHomeGraph(navController)
}
}

fun NavGraphBuilder.addHomeGraph(
navController: NavController,
modifier: Modifier = Modifier
) {
composable(BottomBarTab.CATALOG.route) {
CatalogScreen(navController)
}
composable(BottomBarTab.PROFILE.route) {
ProfileScreen()
}
composable(BottomBarTab.SEARCH.route) {
SearchScreen()
}
composable(GAME_CARD_DETAIL_ROUTE) {
MyCard()
}
}

object MainDestinations {
const val HOME_ROUTE = "home"
const val GAME_CARD_DETAIL_ROUTE = "cardRoute"
}

enum class BottomBarTab(
@StringRes val title: Int,
val icon: ImageVector,
val route: String
) {
CATALOG(R.string.home_catalog, Icons.Outlined.Home, "$HOME_ROUTE/catalog"),
PROFILE(R.string.home_profile, Icons.Outlined.AccountCircle, "$HOME_ROUTE/profile"),
SEARCH(R.string.home_search, Icons.Outlined.Search, "$HOME_ROUTE/search")
}

@Stable
class AppState(
val navController: NavHostController
Expand Down Expand Up @@ -148,6 +121,13 @@ class AppState(
}
}
}

fun navigateToHomeItemDetail(itemId: Int, from: NavBackStackEntry) {
// In order to discard duplicated navigation events, we check the Lifecycle
if (from.lifecycleIsResumed()) {
navController.navigate("${HOME_ITEM_ROUTE}/$itemId")
}
}
}

private fun NavBackStackEntry.lifecycleIsResumed() =
Expand All @@ -164,67 +144,23 @@ private tailrec fun findStartDestination(graph: NavDestination): NavDestination
fun BottomBar(
tabs: Array<BottomBarTab>,
currentRoute: String,
navigateToRoute: (String) -> Unit,
color: Color = Color.White,
contentColor: Color = Color.Black
navigateToRoute: (String) -> Unit
) {
// val routes = remember { tabs.map { it.route } }
// val currentSection = tabs.first { it.route == currentRoute }
Surface(
color = color,
contentColor = contentColor
BottomNavigation(
backgroundColor = colorResource(id = R.color.white)
) {
BottomNavigation {
tabs.forEach { item ->
BottomNavigationItem(
icon = {
Icon(
imageVector = item.icon,
contentDescription = stringResource(id = item.title)
)
},
label = { Text(text = stringResource(id = item.title)) },
selected = currentRoute == item.route,
onClick = { navigateToRoute(item.route) }
)
}
tabs.forEach { item ->
BottomNavigationItem(
icon = {
Icon(
painter = painterResource(id = item.icon),
contentDescription = stringResource(id = item.title)
)
},
label = { Text(text = stringResource(id = item.title)) },
selected = currentRoute == item.route,
onClick = { navigateToRoute(item.route) }
)
}
}
}

@Composable
fun CatalogScreen(navController: NavController) {
Text(
text = "catalog",
modifier = Modifier
.clickable {
navController.navigate(GAME_CARD_DETAIL_ROUTE)
})
}

@Composable
fun ProfileScreen() {
Text("profile")
}

@Composable
fun SearchScreen() {
Text("search")
}

@Composable
fun MyCard() {
Text("my card")
}

@Preview
@Composable
private fun bottomNavPreview() {
ConditionalBottomNavTheme {
BottomBar(
tabs = BottomBarTab.values(),
currentRoute = "home/catalog",
navigateToRoute = { }
)
}
}

0 comments on commit e2c7769

Please sign in to comment.