diff --git a/app/src/main/java/com/sqz/checklist/ui/MainLayout.kt b/app/src/main/java/com/sqz/checklist/ui/MainLayout.kt index c4bcb27..d6c00bb 100644 --- a/app/src/main/java/com/sqz/checklist/ui/MainLayout.kt +++ b/app/src/main/java/com/sqz/checklist/ui/MainLayout.kt @@ -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 @@ -56,7 +58,7 @@ 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 @@ -64,7 +66,8 @@ fun MainLayout(context: Context, view: View, modifier: Modifier = Modifier) { // The else should never happen, never be called else -> NavExtendedButtonData() } - NavBar( + NavBarLayout( + mode = mode, extendedButtonData = extendedButtonData, selected = { index -> index.name == currentRoute }, onNavClick = { index -> @@ -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() } } @@ -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) ) { diff --git a/app/src/main/java/com/sqz/checklist/ui/main/NavBarLayout.kt b/app/src/main/java/com/sqz/checklist/ui/main/NavBarLayout.kt index c889bf4..96c61e4 100644 --- a/app/src/main/java/com/sqz/checklist/ui/main/NavBarLayout.kt +++ b/app/src/main/java/com/sqz/checklist/ui/main/NavBarLayout.kt @@ -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 @@ -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 = { + 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( @@ -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)) @@ -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, "") }, @@ -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 = {} + ) +} diff --git a/app/src/main/java/com/sqz/checklist/ui/main/task/layout/TaskLayoutTopBar.kt b/app/src/main/java/com/sqz/checklist/ui/main/task/layout/TaskLayoutTopBar.kt index eeda4bf..ca51285 100644 --- a/app/src/main/java/com/sqz/checklist/ui/main/task/layout/TaskLayoutTopBar.kt +++ b/app/src/main/java/com/sqz/checklist/ui/main/task/layout/TaskLayoutTopBar.kt @@ -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, )