Update usage of material3 adaptive to be edge-to-edge

Change-Id: I481c79db77bbdd657182f5355200f63e2355f40d
pull/1282/head
Alex Vanyo 9 months ago
parent 16f45c0b1a
commit 0be0bc191f

@ -100,6 +100,7 @@ dependencies {
implementation(libs.androidx.navigation.compose) implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.profileinstaller) implementation(libs.androidx.profileinstaller)
implementation(libs.androidx.tracing.ktx) implementation(libs.androidx.tracing.ktx)
implementation(libs.androidx.window.core)
implementation(libs.kotlinx.coroutines.guava) implementation(libs.kotlinx.coroutines.guava)
implementation(libs.coil.kt) implementation(libs.coil.kt)

@ -123,9 +123,9 @@ androidx.vectordrawable:vectordrawable:1.1.0
androidx.versionedparcelable:versionedparcelable:1.1.1 androidx.versionedparcelable:versionedparcelable:1.1.1
androidx.viewpager:viewpager:1.0.0 androidx.viewpager:viewpager:1.0.0
androidx.window.extensions.core:core:1.0.0 androidx.window.extensions.core:core:1.0.0
androidx.window:window-core-android:1.3.0-alpha02 androidx.window:window-core-android:1.3.0-alpha03
androidx.window:window-core:1.3.0-alpha02 androidx.window:window-core:1.3.0-alpha03
androidx.window:window:1.3.0-alpha02 androidx.window:window:1.3.0-alpha03
androidx.work:work-runtime-ktx:2.9.0 androidx.work:work-runtime-ktx:2.9.0
androidx.work:work-runtime:2.9.0 androidx.work:work-runtime:2.9.0
com.caverock:androidsvg-aar:1.4 com.caverock:androidsvg-aar:1.4

@ -179,6 +179,7 @@ internal fun NiaApp(
Column(Modifier.fillMaxSize()) { Column(Modifier.fillMaxSize()) {
// Show the top app bar on top level destinations. // Show the top app bar on top level destinations.
val destination = appState.currentTopLevelDestination val destination = appState.currentTopLevelDestination
val shouldShowTopAppBar = destination != null
if (destination != null) { if (destination != null) {
NiaTopAppBar( NiaTopAppBar(
titleRes = destination.titleTextId, titleRes = destination.titleTextId,
@ -207,6 +208,13 @@ internal fun NiaApp(
duration = Short, duration = Short,
) == ActionPerformed ) == ActionPerformed
}, },
modifier = if (shouldShowTopAppBar) {
Modifier.consumeWindowInsets(
WindowInsets.safeDrawing.only(WindowInsetsSides.Top),
)
} else {
Modifier
},
) )
} }

@ -17,15 +17,29 @@
package com.google.samples.apps.nowinandroid.ui.interests2pane package com.google.samples.apps.nowinandroid.ui.interests2pane
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.Posture
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.material3.adaptive.allVerticalHingeBounds
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.adaptive.layout.HingePolicy
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
import androidx.compose.material3.adaptive.layout.PaneScaffoldDirective
import androidx.compose.material3.adaptive.layout.calculateStandardPaneScaffoldDirective
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
import androidx.compose.material3.adaptive.occludingVerticalHingeBounds
import androidx.compose.material3.adaptive.separatingVerticalHingeBounds
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
@ -34,6 +48,7 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument import androidx.navigation.navArgument
import androidx.window.core.layout.WindowWidthSizeClass
import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.INTERESTS_ROUTE import com.google.samples.apps.nowinandroid.feature.interests.navigation.INTERESTS_ROUTE
import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_ARG import com.google.samples.apps.nowinandroid.feature.interests.navigation.TOPIC_ID_ARG
@ -76,7 +91,12 @@ internal fun InterestsListDetailScreen(
selectedTopicId: String?, selectedTopicId: String?,
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
) { ) {
val listDetailNavigator = rememberListDetailPaneScaffoldNavigator<Nothing>() val scaffoldDirective = calculateNoContentPaddingScaffoldDirective(
currentWindowAdaptiveInfo(),
)
val listDetailNavigator = rememberListDetailPaneScaffoldNavigator<Nothing>(
scaffoldDirective = scaffoldDirective,
)
BackHandler(listDetailNavigator.canNavigateBack()) { BackHandler(listDetailNavigator.canNavigateBack()) {
listDetailNavigator.navigateBack() listDetailNavigator.navigateBack()
} }
@ -116,6 +136,7 @@ internal fun InterestsListDetailScreen(
} }
} }
}, },
windowInsets = WindowInsets(0, 0, 0, 0),
) )
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
if (selectedTopicId != null) { if (selectedTopicId != null) {
@ -132,3 +153,59 @@ private fun <T> ThreePaneScaffoldNavigator<T>.isListPaneVisible(): Boolean =
@OptIn(ExperimentalMaterial3AdaptiveApi::class) @OptIn(ExperimentalMaterial3AdaptiveApi::class)
private fun <T> ThreePaneScaffoldNavigator<T>.isDetailPaneVisible(): Boolean = private fun <T> ThreePaneScaffoldNavigator<T>.isDetailPaneVisible(): Boolean =
scaffoldValue[ListDetailPaneScaffoldRole.Detail] == PaneAdaptedValue.Expanded scaffoldValue[ListDetailPaneScaffoldRole.Detail] == PaneAdaptedValue.Expanded
/**
* This is a direct clone of [calculateStandardPaneScaffoldDirective] with the only change of
* passing 0 content padding to the panes.
*/
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
private fun calculateNoContentPaddingScaffoldDirective(
windowAdaptiveInfo: WindowAdaptiveInfo,
verticalHingePolicy: HingePolicy = HingePolicy.AvoidSeparating,
): PaneScaffoldDirective {
val maxHorizontalPartitions: Int
val verticalSpacerSize: Dp
when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> {
maxHorizontalPartitions = 1
verticalSpacerSize = 0.dp
}
WindowWidthSizeClass.MEDIUM -> {
maxHorizontalPartitions = 1
verticalSpacerSize = 0.dp
}
else -> {
maxHorizontalPartitions = 2
verticalSpacerSize = 24.dp
}
}
val maxVerticalPartitions: Int
val horizontalSpacerSize: Dp
if (windowAdaptiveInfo.windowPosture.isTabletop) {
maxVerticalPartitions = 2
horizontalSpacerSize = 24.dp
} else {
maxVerticalPartitions = 1
horizontalSpacerSize = 0.dp
}
return PaneScaffoldDirective(
PaddingValues(0.dp),
maxHorizontalPartitions,
verticalSpacerSize,
maxVerticalPartitions,
horizontalSpacerSize,
getExcludedVerticalBounds(windowAdaptiveInfo.windowPosture, verticalHingePolicy),
)
}
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
private fun getExcludedVerticalBounds(posture: Posture, hingePolicy: HingePolicy): List<Rect> {
return when (hingePolicy) {
HingePolicy.AvoidSeparating -> posture.separatingVerticalHingeBounds
HingePolicy.AvoidOccluding -> posture.occludingVerticalHingeBounds
HingePolicy.AlwaysAvoid -> posture.allVerticalHingeBounds
else -> emptyList()
}
}

@ -27,7 +27,7 @@ androidxTestRules = "1.5.0"
androidxTestRunner = "1.5.2" androidxTestRunner = "1.5.2"
androidxTracing = "1.3.0-alpha02" androidxTracing = "1.3.0-alpha02"
androidxUiAutomator = "2.2.0" androidxUiAutomator = "2.2.0"
androidxWindowManager = "1.2.0" androidxWindowManager = "1.3.0-alpha03"
androidxWork = "2.9.0" androidxWork = "2.9.0"
coil = "2.6.0" coil = "2.6.0"
dependencyGuard = "0.4.3" dependencyGuard = "0.4.3"
@ -101,6 +101,7 @@ androidx-test-rules = { group = "androidx.test", name = "rules", version.ref = "
androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidxTestRunner" } androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidxTestRunner" }
androidx-test-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "androidxUiAutomator" } androidx-test-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "androidxUiAutomator" }
androidx-tracing-ktx = { group = "androidx.tracing", name = "tracing-ktx", version.ref = "androidxTracing" } androidx-tracing-ktx = { group = "androidx.tracing", name = "tracing-ktx", version.ref = "androidxTracing" }
androidx-window-core = { group = "androidx.window", name = "window-core", version.ref = "androidxWindowManager" }
androidx-work-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "androidxWork" } androidx-work-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "androidxWork" }
androidx-work-testing = { group = "androidx.work", name = "work-testing", version.ref = "androidxWork" } androidx-work-testing = { group = "androidx.work", name = "work-testing", version.ref = "androidxWork" }
coil-kt = { group = "io.coil-kt", name = "coil", version.ref = "coil" } coil-kt = { group = "io.coil-kt", name = "coil", version.ref = "coil" }

Loading…
Cancel
Save