|
|
@ -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()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|