Change-Id: I02d1058593bbfa25eb7d9f2489b1960792b0e71efeature/adaptive_scaffold
parent
4d65946f95
commit
594e1798d9
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.ui
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarDefaults
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.NavigationBarItemDefaults
|
||||
import androidx.compose.material3.NavigationDrawerItem
|
||||
import androidx.compose.material3.NavigationDrawerItemDefaults
|
||||
import androidx.compose.material3.NavigationRail
|
||||
import androidx.compose.material3.NavigationRailDefaults
|
||||
import androidx.compose.material3.NavigationRailItem
|
||||
import androidx.compose.material3.NavigationRailItemDefaults
|
||||
import androidx.compose.material3.PermanentDrawerSheet
|
||||
import androidx.compose.material3.PermanentNavigationDrawer
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.ScaffoldDefaults
|
||||
import androidx.compose.material3.contentColorFor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.window.layout.WindowMetricsCalculator
|
||||
|
||||
class AdaptiveScaffoldNavigationComponentColors internal constructor(
|
||||
val railContainerColor: Color,
|
||||
val drawerContainerColor: Color,
|
||||
val bottomBarContainerColor: Color,
|
||||
val contentContainerColor: Color,
|
||||
val contentColor: Color,
|
||||
val selectedIconColor: Color,
|
||||
val selectedTextColor: Color,
|
||||
val unselectedIconColor: Color,
|
||||
val unselectedTextColor: Color,
|
||||
val selectedContainerColor: Color,
|
||||
val unselectedContainerColor: Color,
|
||||
)
|
||||
|
||||
object AdaptiveScaffoldNavigationComponentDefaults {
|
||||
@Composable
|
||||
fun colors(
|
||||
railContainerColor: Color = NavigationRailDefaults.ContainerColor,
|
||||
drawerContainerColor: Color = MaterialTheme.colorScheme.surface,
|
||||
bottomBarContainerColor: Color = NavigationBarDefaults.containerColor,
|
||||
contentContainerColor: Color = MaterialTheme.colorScheme.background,
|
||||
contentColor: Color = contentColorFor(contentContainerColor),
|
||||
selectedIconColor: Color = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
selectedTextColor: Color = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
unselectedIconColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
unselectedTextColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
selectedContainerColor: Color = MaterialTheme.colorScheme.secondaryContainer,
|
||||
unselectedContainerColor: Color = MaterialTheme.colorScheme.surface
|
||||
) = AdaptiveScaffoldNavigationComponentColors(
|
||||
railContainerColor = railContainerColor,
|
||||
drawerContainerColor = drawerContainerColor,
|
||||
bottomBarContainerColor = bottomBarContainerColor,
|
||||
contentContainerColor = contentContainerColor,
|
||||
contentColor = contentColor,
|
||||
selectedIconColor = selectedIconColor,
|
||||
selectedTextColor = selectedTextColor,
|
||||
unselectedIconColor = unselectedIconColor,
|
||||
unselectedTextColor = unselectedTextColor,
|
||||
selectedContainerColor = selectedContainerColor,
|
||||
unselectedContainerColor = unselectedContainerColor,
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun <T> AdaptiveScaffold(
|
||||
modifier: Modifier = Modifier,
|
||||
navigationItems: List<T>,
|
||||
navigationItemTitle: @Composable (item: T, isSelected: Boolean) -> Unit,
|
||||
navigationItemIcon: @Composable (item: T, isSelected: Boolean) -> Unit,
|
||||
isItemSelected: @Composable (item: T) -> Boolean,
|
||||
onNavigationItemClick: (item: T) -> Unit,
|
||||
topBar: @Composable () -> Unit = {},
|
||||
snackbarHost: @Composable () -> Unit = {},
|
||||
colors: AdaptiveScaffoldNavigationComponentColors = AdaptiveScaffoldNavigationComponentDefaults.colors(),
|
||||
contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,
|
||||
content: @Composable (padding: PaddingValues) -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
|
||||
val widthDp = metrics.bounds.width() / context.resources.displayMetrics.density
|
||||
|
||||
when {
|
||||
widthDp >= 1240f -> {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = topBar,
|
||||
snackbarHost = snackbarHost,
|
||||
containerColor = colors.contentContainerColor,
|
||||
contentColor = colors.contentColor,
|
||||
contentWindowInsets = contentWindowInsets,
|
||||
) { padding ->
|
||||
PermanentNavigationDrawer(
|
||||
drawerContent = {
|
||||
PermanentDrawerSheet(
|
||||
drawerContainerColor = colors.drawerContainerColor,
|
||||
) {
|
||||
navigationItems.forEach { item ->
|
||||
NavigationDrawerItem(
|
||||
label = { navigationItemTitle(item, isItemSelected(item)) },
|
||||
icon = { navigationItemIcon(item, isItemSelected(item)) },
|
||||
selected = isItemSelected(item),
|
||||
onClick = { onNavigationItemClick(item) },
|
||||
colors = NavigationDrawerItemDefaults.colors(
|
||||
selectedContainerColor = colors.selectedContainerColor,
|
||||
unselectedContainerColor = colors.unselectedContainerColor,
|
||||
selectedIconColor = colors.selectedIconColor,
|
||||
unselectedIconColor = colors.unselectedIconColor,
|
||||
selectedTextColor = colors.selectedTextColor,
|
||||
unselectedTextColor = colors.unselectedTextColor,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(padding),
|
||||
) {
|
||||
content(padding)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
widthDp >= 600f -> {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = topBar,
|
||||
snackbarHost = snackbarHost,
|
||||
containerColor = colors.contentContainerColor,
|
||||
contentColor = colors.contentColor,
|
||||
contentWindowInsets = contentWindowInsets,
|
||||
) { padding ->
|
||||
Row {
|
||||
NavigationRail(
|
||||
containerColor = colors.railContainerColor,
|
||||
) {
|
||||
navigationItems.forEach { item ->
|
||||
NavigationRailItem(
|
||||
label = { navigationItemTitle(item, isItemSelected(item)) },
|
||||
icon = { navigationItemIcon(item, isItemSelected(item)) },
|
||||
selected = isItemSelected(item),
|
||||
onClick = { onNavigationItemClick(item) },
|
||||
colors = NavigationRailItemDefaults.colors(
|
||||
indicatorColor = colors.selectedContainerColor,
|
||||
selectedIconColor = colors.selectedIconColor,
|
||||
unselectedIconColor = colors.unselectedIconColor,
|
||||
selectedTextColor = colors.selectedTextColor,
|
||||
unselectedTextColor = colors.unselectedTextColor,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
content(padding)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
snackbarHost = snackbarHost,
|
||||
bottomBar = {
|
||||
NavigationBar(
|
||||
containerColor = colors.bottomBarContainerColor,
|
||||
) {
|
||||
navigationItems.forEach { item ->
|
||||
NavigationBarItem(
|
||||
label = { navigationItemTitle(item, isItemSelected(item)) },
|
||||
icon = { navigationItemIcon(item, isItemSelected(item)) },
|
||||
selected = isItemSelected(item),
|
||||
onClick = { onNavigationItemClick(item) },
|
||||
colors = NavigationBarItemDefaults.colors(
|
||||
indicatorColor = colors.selectedContainerColor,
|
||||
selectedIconColor = colors.selectedIconColor,
|
||||
unselectedIconColor = colors.unselectedIconColor,
|
||||
selectedTextColor = colors.selectedTextColor,
|
||||
unselectedTextColor = colors.unselectedTextColor,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
containerColor = colors.contentContainerColor,
|
||||
contentColor = colors.contentColor,
|
||||
contentWindowInsets = contentWindowInsets,
|
||||
) { padding ->
|
||||
content(padding)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue