From 14a98de2fad91e1a0f9c2ef19af049e9e4697881 Mon Sep 17 00:00:00 2001 From: Rob Orgiu Date: Thu, 27 Nov 2025 17:17:32 +0100 Subject: [PATCH 1/5] Changes aspect ratio of the wrapping box when the Camera is running in tabletop --- .../com/android/developers/androidify/camera/CameraLayout.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/camera/src/main/java/com/android/developers/androidify/camera/CameraLayout.kt b/feature/camera/src/main/java/com/android/developers/androidify/camera/CameraLayout.kt index 519228b7..46ff6fa3 100644 --- a/feature/camera/src/main/java/com/android/developers/androidify/camera/CameraLayout.kt +++ b/feature/camera/src/main/java/com/android/developers/androidify/camera/CameraLayout.kt @@ -329,7 +329,7 @@ private fun TableTopCameraLayout( Box( modifier = Modifier .weight(1f) - .aspectRatio(1f), + .aspectRatio(9/16f), ) { viewfinder(Modifier) guide(Modifier.fillMaxSize()) @@ -381,7 +381,7 @@ private fun MediumHorizontalCameraLayout( Box( Modifier - .aspectRatio(3 / 4f) + .aspectRatio(9 / 16f) .navigationBarsPadding(), ) { viewfinder(Modifier.fillMaxSize()) From c0e296d4eea4c57a1d1309b34a746bf56248273a Mon Sep 17 00:00:00 2001 From: Rob Orgiu Date: Thu, 27 Nov 2025 17:31:49 +0100 Subject: [PATCH 2/5] Add new check for height size class to avoid cutting the UI --- .../developers/androidify/theme/components/Backgrounds.kt | 6 +++--- .../android/developers/androidify/util/AdaptivePreview.kt | 2 ++ .../com/android/developers/androidify/util/LayoutUtils.kt | 8 +++++++- .../android/developers/androidify/camera/CameraLayout.kt | 6 +++--- .../androidify/creation/EditScreenLayoutType.kt | 5 +++-- .../com/android/developers/androidify/home/AboutScreen.kt | 4 ++-- .../developers/androidify/home/HomeScreenLayoutType.kt | 4 ++-- .../androidify/customize/CustomizeExportLayoutType.kt | 4 ++-- .../developers/androidify/results/ResultsScreen.kt | 4 ++-- 9 files changed, 26 insertions(+), 17 deletions(-) diff --git a/core/theme/src/main/java/com/android/developers/androidify/theme/components/Backgrounds.kt b/core/theme/src/main/java/com/android/developers/androidify/theme/components/Backgrounds.kt index 976546d2..6b799ea0 100644 --- a/core/theme/src/main/java/com/android/developers/androidify/theme/components/Backgrounds.kt +++ b/core/theme/src/main/java/com/android/developers/androidify/theme/components/Backgrounds.kt @@ -43,13 +43,13 @@ import com.android.developers.androidify.theme.R import com.android.developers.androidify.util.LargeScreensPreview import com.android.developers.androidify.util.PhonePreview import com.android.developers.androidify.util.dpToPx -import com.android.developers.androidify.util.isAtLeastMedium +import com.android.developers.androidify.util.isWidthAtLeastMedium @Composable fun SquiggleBackground( modifier: Modifier = Modifier, offsetHeightFraction: Float = 0f, - isMediumWindowSize: Boolean = isAtLeastMedium(), + isMediumWindowSize: Boolean = isWidthAtLeastMedium(), ) { val vectorBackground = rememberVectorPainter(ImageVector.vectorResource(R.drawable.squiggle)) @@ -113,7 +113,7 @@ private fun ResultsBackgroundPhonePreview() { @Composable fun ResultsBackground( modifier: Modifier = Modifier, - isMediumWindowSize: Boolean = isAtLeastMedium(), + isMediumWindowSize: Boolean = isWidthAtLeastMedium(), ) { Box( modifier = modifier diff --git a/core/util/src/main/java/com/android/developers/androidify/util/AdaptivePreview.kt b/core/util/src/main/java/com/android/developers/androidify/util/AdaptivePreview.kt index 63e7626f..d1721a95 100644 --- a/core/util/src/main/java/com/android/developers/androidify/util/AdaptivePreview.kt +++ b/core/util/src/main/java/com/android/developers/androidify/util/AdaptivePreview.kt @@ -21,8 +21,10 @@ import androidx.compose.ui.tooling.preview.Devices.PIXEL_7_PRO import androidx.compose.ui.tooling.preview.Devices.PIXEL_FOLD import androidx.compose.ui.tooling.preview.Devices.PIXEL_TABLET import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp @Preview(device = PIXEL_7_PRO, name = "Phone preview") +@Preview(widthDp = 891, heightDp = 411, name = "Phone landscape preview", ) annotation class PhonePreview @Preview(device = PIXEL_3A_XL, name = "Phone small preview", heightDp = 300, widthDp = 500) diff --git a/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt b/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt index 6bf821d6..326b9820 100644 --- a/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt +++ b/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt @@ -38,11 +38,17 @@ fun calculateWindowSizeClass(): WindowSizeClass { } @Composable -fun isAtLeastMedium(): Boolean { +fun isWidthAtLeastMedium(): Boolean { val sizeClass = calculateWindowSizeClass() return sizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) } +@Composable +fun isHeightAtLeastMedium(): Boolean { + val sizeClass = calculateWindowSizeClass() + return sizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND) +} + /*** * This function is useful to limit the number of buttons when the window is too small to show * everything that should otherwise appear on the screen. diff --git a/feature/camera/src/main/java/com/android/developers/androidify/camera/CameraLayout.kt b/feature/camera/src/main/java/com/android/developers/androidify/camera/CameraLayout.kt index 46ff6fa3..2faee681 100644 --- a/feature/camera/src/main/java/com/android/developers/androidify/camera/CameraLayout.kt +++ b/feature/camera/src/main/java/com/android/developers/androidify/camera/CameraLayout.kt @@ -56,7 +56,7 @@ import com.android.developers.androidify.theme.TertiaryContainer import com.android.developers.androidify.util.FoldablePreviewParameters import com.android.developers.androidify.util.FoldablePreviewParametersProvider import com.android.developers.androidify.util.allowsFullContent -import com.android.developers.androidify.util.isAtLeastMedium +import com.android.developers.androidify.util.isWidthAtLeastMedium import com.android.developers.androidify.util.shouldShowTabletopLayout import com.android.developers.androidify.util.supportsTabletop import com.android.developers.androidify.xr.LocalSpatialCapabilities @@ -111,7 +111,7 @@ internal fun CameraLayout( surfaceAspectRatio, ) - isAtLeastMedium() && shouldShowTabletopLayout( + isWidthAtLeastMedium() && shouldShowTabletopLayout( supportsTabletop = supportsTabletop, isTabletop = isTabletop, ) -> TableTopSupportedCameraLayout( @@ -125,7 +125,7 @@ internal fun CameraLayout( isTabletop = isTabletop, ) - isAtLeastMedium() && maxWidth > maxHeight -> MediumHorizontalCameraLayout( + isWidthAtLeastMedium() && maxWidth > maxHeight -> MediumHorizontalCameraLayout( viewfinder, captureButton, flipCameraButton, diff --git a/feature/creation/src/main/java/com/android/developers/androidify/creation/EditScreenLayoutType.kt b/feature/creation/src/main/java/com/android/developers/androidify/creation/EditScreenLayoutType.kt index 60e697b8..22eacbd9 100644 --- a/feature/creation/src/main/java/com/android/developers/androidify/creation/EditScreenLayoutType.kt +++ b/feature/creation/src/main/java/com/android/developers/androidify/creation/EditScreenLayoutType.kt @@ -16,7 +16,8 @@ package com.android.developers.androidify.creation import androidx.compose.runtime.Composable -import com.android.developers.androidify.util.isAtLeastMedium +import com.android.developers.androidify.util.isHeightAtLeastMedium +import com.android.developers.androidify.util.isWidthAtLeastMedium import com.android.developers.androidify.xr.LocalSpatialCapabilities enum class EditScreenLayoutType { @@ -29,7 +30,7 @@ enum class EditScreenLayoutType { fun calculateLayoutType(enableXr: Boolean = false): EditScreenLayoutType { return when { LocalSpatialCapabilities.current.isSpatialUiEnabled && enableXr -> EditScreenLayoutType.Spatial - isAtLeastMedium() -> EditScreenLayoutType.Medium + isWidthAtLeastMedium() && isHeightAtLeastMedium() -> EditScreenLayoutType.Medium else -> EditScreenLayoutType.Compact } } diff --git a/feature/home/src/main/java/com/android/developers/androidify/home/AboutScreen.kt b/feature/home/src/main/java/com/android/developers/androidify/home/AboutScreen.kt index 870f146e..dda11140 100644 --- a/feature/home/src/main/java/com/android/developers/androidify/home/AboutScreen.kt +++ b/feature/home/src/main/java/com/android/developers/androidify/home/AboutScreen.kt @@ -68,7 +68,7 @@ import com.android.developers.androidify.theme.components.SecondaryOutlinedButto import com.android.developers.androidify.theme.sharedBoundsReveal import com.android.developers.androidify.util.LargeScreensPreview import com.android.developers.androidify.util.PhonePreview -import com.android.developers.androidify.util.isAtLeastMedium +import com.android.developers.androidify.util.isWidthAtLeastMedium @Composable fun AboutScreen( @@ -95,7 +95,7 @@ fun AboutScreenContents( onPrivacyClicked: () -> Unit, onLicensesClicked: () -> Unit, xrEnabled: Boolean = false, - isMediumWindowSize: Boolean = isAtLeastMedium(), + isMediumWindowSize: Boolean = isWidthAtLeastMedium(), ) { val bottomButtons = @Composable { FooterButtons( diff --git a/feature/home/src/main/java/com/android/developers/androidify/home/HomeScreenLayoutType.kt b/feature/home/src/main/java/com/android/developers/androidify/home/HomeScreenLayoutType.kt index 2828f9e2..7ef3e783 100644 --- a/feature/home/src/main/java/com/android/developers/androidify/home/HomeScreenLayoutType.kt +++ b/feature/home/src/main/java/com/android/developers/androidify/home/HomeScreenLayoutType.kt @@ -17,7 +17,7 @@ package com.android.developers.androidify.home import androidx.compose.runtime.Composable import androidx.xr.compose.platform.LocalSpatialCapabilities -import com.android.developers.androidify.util.isAtLeastMedium +import com.android.developers.androidify.util.isWidthAtLeastMedium enum class HomeScreenLayoutType { Compact, @@ -29,7 +29,7 @@ enum class HomeScreenLayoutType { fun calculateLayoutType(enableXr: Boolean = false): HomeScreenLayoutType { return when { LocalSpatialCapabilities.current.isSpatialUiEnabled && enableXr -> HomeScreenLayoutType.Spatial - isAtLeastMedium() -> HomeScreenLayoutType.Medium + isWidthAtLeastMedium() -> HomeScreenLayoutType.Medium else -> HomeScreenLayoutType.Compact } } diff --git a/feature/results/src/main/java/com/android/developers/androidify/customize/CustomizeExportLayoutType.kt b/feature/results/src/main/java/com/android/developers/androidify/customize/CustomizeExportLayoutType.kt index 31ad2ed5..84b615c2 100644 --- a/feature/results/src/main/java/com/android/developers/androidify/customize/CustomizeExportLayoutType.kt +++ b/feature/results/src/main/java/com/android/developers/androidify/customize/CustomizeExportLayoutType.kt @@ -17,7 +17,7 @@ package com.android.developers.androidify.customize import androidx.compose.runtime.Composable import androidx.xr.compose.platform.LocalSpatialCapabilities -import com.android.developers.androidify.util.isAtLeastMedium +import com.android.developers.androidify.util.isWidthAtLeastMedium enum class CustomizeExportLayoutType { Compact, @@ -29,7 +29,7 @@ enum class CustomizeExportLayoutType { fun calculateLayoutType(enableXr: Boolean = false): CustomizeExportLayoutType { return when { LocalSpatialCapabilities.current.isSpatialUiEnabled && enableXr -> CustomizeExportLayoutType.Spatial - isAtLeastMedium() -> CustomizeExportLayoutType.Medium + isWidthAtLeastMedium() -> CustomizeExportLayoutType.Medium else -> CustomizeExportLayoutType.Compact } } diff --git a/feature/results/src/main/java/com/android/developers/androidify/results/ResultsScreen.kt b/feature/results/src/main/java/com/android/developers/androidify/results/ResultsScreen.kt index cdc2543c..d9c44f81 100644 --- a/feature/results/src/main/java/com/android/developers/androidify/results/ResultsScreen.kt +++ b/feature/results/src/main/java/com/android/developers/androidify/results/ResultsScreen.kt @@ -57,7 +57,7 @@ import com.android.developers.androidify.theme.components.AndroidifyTopAppBar import com.android.developers.androidify.theme.components.ResultsBackground import com.android.developers.androidify.util.AdaptivePreview import com.android.developers.androidify.util.SmallPhonePreview -import com.android.developers.androidify.util.isAtLeastMedium +import com.android.developers.androidify.util.isWidthAtLeastMedium import com.android.developers.androidify.xr.RequestFullSpaceIconButton import com.android.developers.androidify.xr.RequestHomeSpaceIconButton import com.android.developers.androidify.xr.couldRequestFullSpace @@ -129,7 +129,7 @@ fun ResultsScreenContents( val topBar = @Composable { AndroidifyTopAppBar( backEnabled = true, - isMediumWindowSize = isAtLeastMedium(), + isMediumWindowSize = isWidthAtLeastMedium(), onBackPressed = { onBackPress() }, From d18a87a7e9967edf3372ac3eae1d9ac1ba1fa08b Mon Sep 17 00:00:00 2001 From: Rob Orgiu Date: Thu, 27 Nov 2025 17:41:32 +0100 Subject: [PATCH 3/5] Add preview for Main creation pane --- .../androidify/creation/PromptTypePager.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/feature/creation/src/main/java/com/android/developers/androidify/creation/PromptTypePager.kt b/feature/creation/src/main/java/com/android/developers/androidify/creation/PromptTypePager.kt index eeae9afb..6e9e7a64 100644 --- a/feature/creation/src/main/java/com/android/developers/androidify/creation/PromptTypePager.kt +++ b/feature/creation/src/main/java/com/android/developers/androidify/creation/PromptTypePager.kt @@ -57,7 +57,9 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.android.developers.androidify.data.DropBehaviourFactory import com.android.developers.androidify.theme.AndroidifyTheme +import com.android.developers.androidify.theme.SharedElementContextPreview import com.android.developers.androidify.theme.components.HorizontalToolbar +import com.android.developers.androidify.util.PhonePreview import kotlinx.coroutines.launch @Composable @@ -111,6 +113,7 @@ fun MainCreationPane( } } + @Composable private fun PromptTypePager( modifier: Modifier = Modifier, @@ -186,3 +189,22 @@ private fun PromptTypeToolbarPreview() { ) } } + +@Preview +@Composable +private fun PromptTypeMainPreview() { + AndroidifyTheme { + SharedElementContextPreview { + MainCreationPane( + uiState = CreationState(), + dropBehaviourFactory = fakeDropBehaviourFactory, + onCameraPressed = { }, + onChooseImageClicked = {}, + onUndoPressed = {}, + onPromptGenerationPressed = {}, + onSelectedPromptOptionChanged = {}, + onDropCallback = {} + ) + } + } +} From fb06c01c215d02673263dec38e863113f1e54738 Mon Sep 17 00:00:00 2001 From: Rob Orgiu Date: Thu, 27 Nov 2025 18:03:33 +0100 Subject: [PATCH 4/5] Rearrange buttons to avoid scrolling vertically on phone landscape --- .../developers/androidify/util/LayoutUtils.kt | 6 ++ .../androidify/creation/PhotoPrompt.kt | 61 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt b/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt index 326b9820..7129293b 100644 --- a/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt +++ b/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt @@ -49,6 +49,12 @@ fun isHeightAtLeastMedium(): Boolean { return sizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND) } +@Composable +fun isHorizontalWindow(): Boolean { + val sizeClass = calculateWindowSizeClass() + return sizeClass.minWidthDp >= sizeClass.minHeightDp +} + /*** * This function is useful to limit the number of buttons when the window is too small to show * everything that should otherwise appear on the screen. diff --git a/feature/creation/src/main/java/com/android/developers/androidify/creation/PhotoPrompt.kt b/feature/creation/src/main/java/com/android/developers/androidify/creation/PhotoPrompt.kt index 75487846..aac2c1d4 100644 --- a/feature/creation/src/main/java/com/android/developers/androidify/creation/PhotoPrompt.kt +++ b/feature/creation/src/main/java/com/android/developers/androidify/creation/PhotoPrompt.kt @@ -98,6 +98,7 @@ import com.android.developers.androidify.theme.components.SecondaryOutlinedButto import com.android.developers.androidify.theme.sharedBoundsRevealWithShapeMorph import com.android.developers.androidify.theme.sharedBoundsWithDefaults import com.android.developers.androidify.util.dashedRoundedRectBorder +import com.android.developers.androidify.util.isHorizontalWindow import com.android.developers.androidify.creation.R as CreationR @Composable @@ -169,6 +170,27 @@ private fun UploadEmptyState( onCameraPressed: () -> Unit, onChooseImagePress: () -> Unit, modifier: Modifier = Modifier, +) { + if (isHorizontalWindow()) { + HorizontallyAlignedUploadEmptyState( + onCameraPressed = onCameraPressed, + onChooseImagePress = onChooseImagePress, + modifier = modifier, + ) + } else { + VerticallyAlignedUploadEmptyState( + onCameraPressed = onCameraPressed, + onChooseImagePress = onChooseImagePress, + modifier = modifier, + ) + } +} + +@Composable +private fun VerticallyAlignedUploadEmptyState( + onCameraPressed: () -> Unit, + onChooseImagePress: () -> Unit, + modifier: Modifier = Modifier, ) { Column( modifier = modifier @@ -206,6 +228,45 @@ private fun UploadEmptyState( } } +@Composable +private fun HorizontallyAlignedUploadEmptyState( + onCameraPressed: () -> Unit, + onChooseImagePress: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically, + ) { + TakePhotoButton(onCameraPressed) + Text( + stringResource(CreationR.string.photo_picker_title), + fontSize = 28.sp, + textAlign = TextAlign.Center, + lineHeight = 40.sp, + minLines = 2, + maxLines = 2, + ) + SecondaryOutlinedButton( + onClick = { + onChooseImagePress() + }, + leadingIcon = { + Image( + painterResource(CreationR.drawable.choose_picture_image), + contentDescription = null, + modifier = Modifier + .padding(end = 8.dp) + .size(24.dp), + ) + }, + buttonText = stringResource(CreationR.string.photo_picker_choose_photo_label), + ) + } +} + @Composable private fun TakePhotoButton(onCameraPressed: () -> Unit) { val interactionSource = remember { MutableInteractionSource() } From e9d3e553027b9a82fc60202b06c7b0e353d74034 Mon Sep 17 00:00:00 2001 From: Rob Orgiu Date: Thu, 27 Nov 2025 18:17:25 +0100 Subject: [PATCH 5/5] Fix function calling WSC calculation twice --- .../com/android/developers/androidify/util/LayoutUtils.kt | 5 +++-- .../developers/androidify/creation/EditScreenLayoutType.kt | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt b/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt index 7129293b..f3257813 100644 --- a/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt +++ b/core/util/src/main/java/com/android/developers/androidify/util/LayoutUtils.kt @@ -44,9 +44,10 @@ fun isWidthAtLeastMedium(): Boolean { } @Composable -fun isHeightAtLeastMedium(): Boolean { +fun areBothWindowDimensionsAtLeastMedium(): Boolean { val sizeClass = calculateWindowSizeClass() - return sizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND) + return sizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND) && + sizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) } @Composable diff --git a/feature/creation/src/main/java/com/android/developers/androidify/creation/EditScreenLayoutType.kt b/feature/creation/src/main/java/com/android/developers/androidify/creation/EditScreenLayoutType.kt index 22eacbd9..22e3fd3c 100644 --- a/feature/creation/src/main/java/com/android/developers/androidify/creation/EditScreenLayoutType.kt +++ b/feature/creation/src/main/java/com/android/developers/androidify/creation/EditScreenLayoutType.kt @@ -16,8 +16,7 @@ package com.android.developers.androidify.creation import androidx.compose.runtime.Composable -import com.android.developers.androidify.util.isHeightAtLeastMedium -import com.android.developers.androidify.util.isWidthAtLeastMedium +import com.android.developers.androidify.util.areBothWindowDimensionsAtLeastMedium import com.android.developers.androidify.xr.LocalSpatialCapabilities enum class EditScreenLayoutType { @@ -30,7 +29,7 @@ enum class EditScreenLayoutType { fun calculateLayoutType(enableXr: Boolean = false): EditScreenLayoutType { return when { LocalSpatialCapabilities.current.isSpatialUiEnabled && enableXr -> EditScreenLayoutType.Spatial - isWidthAtLeastMedium() && isHeightAtLeastMedium() -> EditScreenLayoutType.Medium + areBothWindowDimensionsAtLeastMedium() -> EditScreenLayoutType.Medium else -> EditScreenLayoutType.Compact } }