Skip to content

Show single pane on phone in landscape #1321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Jetcaster/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ dependencies {
implementation(libs.androidx.navigation.compose)

implementation(libs.androidx.window)
implementation(libs.androidx.window.core)

implementation(libs.accompanist.adaptive)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,19 @@ import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
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.PaneAdaptedValue
import androidx.compose.material3.adaptive.layout.PaneScaffoldDirective
import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold
import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
import androidx.compose.material3.adaptive.navigation.rememberSupportingPaneScaffoldNavigator
import androidx.compose.material3.adaptive.occludingVerticalHingeBounds
import androidx.compose.material3.adaptive.separatingVerticalHingeBounds
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable
Expand All @@ -82,16 +90,20 @@ import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
import coil.compose.AsyncImage
import com.example.jetcaster.R
import com.example.jetcaster.core.data.model.CategoryInfo
Expand Down Expand Up @@ -142,6 +154,77 @@ private fun <T> ThreePaneScaffoldNavigator<T>.isMainPaneHidden(): Boolean {
return scaffoldValue[SupportingPaneScaffoldRole.Main] == PaneAdaptedValue.Hidden
}

/**
* Copied from `calculatePaneScaffoldDirective()` in [PaneScaffoldDirective], with modifications to
* only show 1 pane horizontally if either width or height size class is compact.
*/
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
fun calculateScaffoldDirective(
windowAdaptiveInfo: WindowAdaptiveInfo,
verticalHingePolicy: HingePolicy = HingePolicy.AvoidSeparating
): PaneScaffoldDirective {
val maxHorizontalPartitions: Int
val verticalSpacerSize: Dp
if (windowAdaptiveInfo.windowSizeClass.isCompact()) {
// Window width or height is compact. Limit to 1 pane horizontally.
maxHorizontalPartitions = 1
verticalSpacerSize = 0.dp
} else {
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
}

val defaultPanePreferredWidth = 360.dp

return PaneScaffoldDirective(
maxHorizontalPartitions,
verticalSpacerSize,
maxVerticalPartitions,
horizontalSpacerSize,
defaultPanePreferredWidth,
getExcludedVerticalBounds(windowAdaptiveInfo.windowPosture, verticalHingePolicy)
)
}

/**
* Copied from `getExcludedVerticalBounds()` in [PaneScaffoldDirective] since it is private.
*/
@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()
}
}

private fun androidx.window.core.layout.WindowSizeClass.isCompact(): Boolean =
Copy link
Contributor Author

@jdkoren jdkoren Apr 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are currently two different WindowSizeClass symbols, one in androidx-window (used by the adaptive deps), and one in material3-window-size-class. I think things are moving towards the androidx-window one, and I have a mind to migrate all usages of the other, but not sure if this PR is the right place for that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for calling that out. Yeah we can make that migration on a separate PR

windowWidthSizeClass == WindowWidthSizeClass.COMPACT ||
windowHeightSizeClass == WindowHeightSizeClass.COMPACT

@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun MainScreen(
Expand All @@ -150,7 +233,9 @@ fun MainScreen(
viewModel: HomeViewModel = hiltViewModel()
) {
val viewState by viewModel.state.collectAsStateWithLifecycle()
val navigator = rememberSupportingPaneScaffoldNavigator<String>()
val navigator = rememberSupportingPaneScaffoldNavigator<String>(
scaffoldDirective = calculateScaffoldDirective(currentWindowAdaptiveInfo())
)
BackHandler(enabled = navigator.canNavigateBack()) {
navigator.navigateBack()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.PlaylistAdd
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.rounded.PlayCircleFilled
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
Expand Down Expand Up @@ -123,7 +123,7 @@ private fun EpisodeListItemFooter(
modifier = Modifier
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(bounded = false, radius = 24.dp)
indication = rememberRipple(bounded = false, radius = 24.dp)
) { /* TODO */ }
.size(48.dp)
.padding(6.dp)
Expand Down
9 changes: 4 additions & 5 deletions Jetcaster/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ androidx-appcompat = "1.6.1"
androidx-benchmark = "1.2.3"
androidx-benchmark-junit4 = "1.2.3"
androidx-compose-bom = "2024.03.00"
androidx-compose-latest = "1.7.0-alpha05"
androidx-compose-material3-adaptive = "1.0.0-alpha09"
androidx-compose-material3-latest = "1.3.0-alpha03"
androidx-compose-material3-adaptive = "1.0.0-alpha10"
androidx-constraintlayout = "1.0.1"
androidx-corektx = "1.13.0-beta01"
androidx-glance = "1.0.0"
Expand Down Expand Up @@ -87,14 +85,14 @@ androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref =
androidx-compose-foundation = { module = "androidx.compose.foundation:foundation" }
androidx-compose-foundation-layout = { module = "androidx.compose.foundation:foundation-layout" }
androidx-compose-material-iconsExtended = { module = "androidx.compose.material:material-icons-extended" }
androidx-compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "androidx-compose-material3-latest" }
androidx-compose-material3 = { module = "androidx.compose.material3:material3" }
androidx-compose-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive", version.ref = "androidx-compose-material3-adaptive" }
androidx-compose-material3-adaptive-layout = { group = "androidx.compose.material3.adaptive", name = "adaptive-layout", version.ref = "androidx-compose-material3-adaptive" }
androidx-compose-material3-adaptive-navigation = { group = "androidx.compose.material3.adaptive", name = "adaptive-navigation", version.ref = "androidx-compose-material3-adaptive" }
androidx-compose-material3-window = { module = "androidx.compose.material3:material3-window-size-class" }
androidx-compose-runtime = { module = "androidx.compose.runtime:runtime" }
androidx-compose-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata" }
androidx-compose-ui = { module = "androidx.compose.ui:ui", version.ref = "androidx-compose-latest" }
androidx-compose-ui = { module = "androidx.compose.ui:ui"}
androidx-compose-ui-googlefonts = { module = "androidx.compose.ui:ui-text-google-fonts" }
androidx-compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics" }
androidx-compose-ui-test = { module = "androidx.compose.ui:ui-test" }
Expand Down Expand Up @@ -134,6 +132,7 @@ androidx-test-uiautomator = { module = "androidx.test.uiautomator:uiautomator",
androidx-tv-foundation = { module = "androidx.tv:tv-foundation", version.ref = "androidx-tv-foundation" }
androidx-tv-material = { module = "androidx.tv:tv-material", version.ref = "androidx-tv-material" }
androidx-window = { module = "androidx.window:window", version.ref = "androidx-window" }
androidx-window-core = { module = "androidx.window:window-core", version.ref = "androidx-window" }
coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
core-jdk-desugaring = { module = "com.android.tools:desugar_jdk_libs", version.ref = "jdkDesugar" }
google-android-material = { module = "com.google.android.material:material", version.ref = "material" }
Expand Down