Skip to content

Commit

Permalink
Added navigation rail bar
Browse files Browse the repository at this point in the history
[Added navigation rail when screen is landscape]
[Changed top bar color in topBarForLowScreen]
  • Loading branch information
Z-Siqi committed Oct 16, 2024
1 parent e50a034 commit acc4bd3
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 21 deletions.
23 changes: 19 additions & 4 deletions app/src/main/java/com/sqz/checklist/ui/MainLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalConfiguration
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.sqz.checklist.ui.main.NavBar
import com.sqz.checklist.ui.main.NavBarLayout
import com.sqz.checklist.ui.main.NavExtendedButtonData
import com.sqz.checklist.ui.main.NavMode
import com.sqz.checklist.ui.main.task.TaskLayoutViewModel
import com.sqz.checklist.ui.main.task.history.HistoryTopBar
import com.sqz.checklist.ui.main.task.history.TaskHistory
Expand Down Expand Up @@ -56,15 +58,16 @@ fun MainLayout(context: Context, view: View, modifier: Modifier = Modifier) {
val taskHistoryViewModel: TaskHistoryViewModel = viewModel()

// Navigation bar
val mainNavigationBar = @Composable {
val mainNavigationBar: @Composable (mode: NavMode) -> Unit = { mode ->
@Suppress("OPT_IN_USAGE_FUTURE_ERROR") val extendedButtonData =
when (currentRoute) {
// TaskLayout Extended Nav Button function
MainLayoutNav.TaskLayout.name -> taskExtendedNavButton(view, taskLayoutViewModel)
// The else should never happen, never be called
else -> NavExtendedButtonData()
}
NavBar(
NavBarLayout(
mode = mode,
extendedButtonData = extendedButtonData,
selected = { index -> index.name == currentRoute },
onNavClick = { index ->
Expand Down Expand Up @@ -106,6 +109,14 @@ fun MainLayout(context: Context, view: View, modifier: Modifier = Modifier) {
})
}

// Set Navigation bar mode (Navigation Bar or Navigation Rail)
val localConfig = LocalConfiguration.current
val screenIsWidth = localConfig.screenWidthDp > localConfig.screenHeightDp * 1.2
val navMode = if (!screenIsWidth) NavMode.NavBar else NavMode.Disable
val navRailMode = if (screenIsWidth) NavMode.NavRail else NavMode.Disable
val navigationBar = @Composable { mainNavigationBar(navMode) }
val navigationRailBar = @Composable { mainNavigationBar(navRailMode) }

// Layout
val nulLog = { Log.d("MainLayout", "Navigation bar or Top bar is disable") }
val nul = @Composable { Spacer(modifier = modifier).also { nulLog() } }
Expand All @@ -118,7 +129,11 @@ fun MainLayout(context: Context, view: View, modifier: Modifier = Modifier) {
bottomBar = when (currentRoute) {
MainLayoutNav.TaskHistory.name -> taskHistoryNavBar
MainLayoutNav.Unknown.name -> nul
else -> mainNavigationBar
else -> navigationBar
},
navigationRail = when (currentRoute) {
MainLayoutNav.TaskLayout.name -> navigationRailBar
else -> nul
},
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection)
) {
Expand Down
137 changes: 121 additions & 16 deletions app/src/main/java/com/sqz/checklist/ui/main/NavBarLayout.kt
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
package com.sqz.checklist.ui.main

import android.util.Log
import androidx.compose.foundation.BasicTooltipBox
import androidx.compose.foundation.BasicTooltipState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material3.DividerDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.NavigationRailItemDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.VerticalDivider
Expand All @@ -41,36 +49,58 @@ data class NavExtendedButtonData @OptIn(ExperimentalFoundationApi::class) constr
val onClick: () -> Unit = {},
)

enum class NavMode { NavBar, NavRail, Disable }

/**
* Main Navigation Bar Layout
*/
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun NavBar(
fun NavBarLayout(
mode: NavMode,
extendedButtonData: NavExtendedButtonData,
selected: (index: MainLayoutNav) -> Boolean,
onNavClick: (index: MainLayoutNav) -> Unit,
modifier: Modifier = Modifier
) {
data class Items(
val text: String,
val icon: Int
)
) = when (mode) {
NavMode.NavBar -> NavBar(extendedButtonData, selected, onNavClick, modifier)
NavMode.NavRail -> NavRailBar(extendedButtonData, selected, onNavClick, modifier)
NavMode.Disable -> {
val nulLog = { Log.d("NavBarLayout", "The navigation bar is disable") }
Spacer(modifier = modifier).also { nulLog() }
}
}

private data class Items(val text: String, val icon: Int) // Navigation bar items

val items = listOf( //Navigation bar buttons
private val items: @Composable () -> List<Items> = {
listOf(
//Navigation bar buttons
Items(stringResource(R.string.tasks), R.drawable.task_icon), //id: 0
)
}
private val selectedInNav: (index: Int) -> MainLayoutNav = { index ->
when (index) { //Link items list id to Navigation
0 -> MainLayoutNav.TaskLayout
else -> MainLayoutNav.Unknown
}
}

/** Navigation Bar **/
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
private fun NavBar(
extendedButtonData: NavExtendedButtonData,
selected: (index: MainLayoutNav) -> Boolean,
onNavClick: (index: MainLayoutNav) -> Unit,
modifier: Modifier = Modifier
) {
NavigationBar(
modifier = modifier,
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
) {
Spacer(modifier = modifier.weight(0.5f))
items.forEachIndexed { index, item ->
val selectedInNav = when (index) { //Link items list id to Navigation
0 -> MainLayoutNav.TaskLayout
else -> MainLayoutNav.Unknown
}
items().forEachIndexed { index, item ->
NavigationBarItem(
modifier = modifier.weight(1f),
colors = NavigationBarItemDefaults.colors(
Expand All @@ -86,8 +116,8 @@ fun NavBar(
)
},
label = { Text(item.text) },
selected = selected(selectedInNav),
onClick = { onNavClick(selectedInNav) }
selected = selected(selectedInNav(index)),
onClick = { onNavClick(selectedInNav(index)) }
)
}
Spacer(modifier = modifier.weight(0.5f))
Expand Down Expand Up @@ -115,10 +145,70 @@ fun NavBar(
}
}

/** Navigation Rail **/
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
private fun NavRailBar(
extendedButtonData: NavExtendedButtonData,
selected: (index: MainLayoutNav) -> Boolean,
onNavClick: (index: MainLayoutNav) -> Unit,
modifier: Modifier = Modifier
) {
NavigationRail(
modifier = modifier,
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
) {
Spacer(modifier = modifier.weight(0.5f))
items().forEachIndexed { index, item ->
NavigationRailItem(
modifier = modifier.weight(1f),
colors = NavigationRailItemDefaults.colors(
indicatorColor = MaterialTheme.colorScheme.inversePrimary,
selectedIconColor = MaterialTheme.colorScheme.inverseSurface,
disabledIconColor = MaterialTheme.colorScheme.primary
),
icon = {
Icon(
painter = painterResource(id = item.icon),
contentDescription = item.text,
modifier = modifier.size(24.dp, 24.dp)
)
},
label = { Text(item.text) },
selected = selected(selectedInNav(index)),
onClick = { onNavClick(selectedInNav(index)) }
)
}
Spacer(modifier = modifier.weight(0.5f))
HorizontalDivider(
modifier = modifier.width(50.dp), color = if (isSystemInDarkTheme()) {
MaterialTheme.colorScheme.onSurface
} else DividerDefaults.color
)
Column(modifier = modifier.weight(1f), verticalArrangement = Arrangement.Center) {
BasicTooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
tooltip = extendedButtonData.tooltipContent,
state = extendedButtonData.tooltipState
) {
NavigationRailItem(
modifier = modifier,
colors = NavigationRailItemDefaults.colors(MaterialTheme.colorScheme.primary),
icon = extendedButtonData.icon,
label = extendedButtonData.label,
selected = false,
onClick = extendedButtonData.onClick
)
}
}
}
}

@Preview
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun Preview() {
private fun NavPreview() {
NavBar(
extendedButtonData = NavExtendedButtonData(
icon = { Icon(Icons.Filled.AddCircle, "") },
Expand All @@ -129,3 +219,18 @@ private fun Preview() {
), selected = { true }, onNavClick = {}
)
}

@Preview
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun NavRailPreview() {
NavRailBar(
extendedButtonData = NavExtendedButtonData(
icon = { Icon(Icons.Filled.AddCircle, "") },
label = { Text("TEST") },
tooltipContent = { Text("TEST") },
tooltipState = BasicTooltipState(),
onClick = {}
), selected = { true }, onNavClick = {}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ fun TaskLayoutTopBar(
}

val colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
containerColor = if (topBarForLowScreen) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.primary,
scrolledContainerColor = MaterialTheme.colorScheme.secondaryContainer,
)
Expand Down

0 comments on commit acc4bd3

Please sign in to comment.