Skip to content

Commit aae3e1e

Browse files
authored
Merge pull request #134 from devbridie/feature/xr/loading-screen
Create a Spatial layout for the Loading portion of CreationScreen
2 parents 291e7e7 + 2314ff6 commit aae3e1e

File tree

10 files changed

+251
-53
lines changed

10 files changed

+251
-53
lines changed

core/theme/src/main/java/com/android/developers/androidify/theme/components/Backgrounds.kt

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
3636
import androidx.compose.ui.graphics.vector.rememberVectorPainter
3737
import androidx.compose.ui.layout.ContentScale
3838
import androidx.compose.ui.res.vectorResource
39-
import androidx.compose.ui.tooling.preview.Devices.PIXEL_TABLET
40-
import androidx.compose.ui.tooling.preview.Preview
4139
import androidx.compose.ui.unit.IntOffset
4240
import androidx.compose.ui.unit.dp
4341
import com.android.developers.androidify.theme.AndroidifyTheme
@@ -80,31 +78,6 @@ fun SquiggleBackground(
8078
}
8179
}
8280

83-
/**
84-
* Background squiggle that tries to fit in its parent.
85-
*/
86-
@Composable
87-
fun SquiggleBackgroundFull() {
88-
val vectorBackground =
89-
rememberVectorPainter(ImageVector.vectorResource(R.drawable.squiggle_full))
90-
Box(modifier = Modifier.fillMaxSize()) {
91-
Image(
92-
painter = vectorBackground,
93-
contentDescription = null,
94-
modifier = Modifier.fillMaxSize(),
95-
contentScale = ContentScale.Fit,
96-
)
97-
}
98-
}
99-
100-
@Preview(device = PIXEL_TABLET)
101-
@Composable
102-
fun SquiggleFullImagePreview() {
103-
AndroidifyTheme {
104-
SquiggleBackgroundFull()
105-
}
106-
}
107-
10881
@LargeScreensPreview
10982
@Composable
11083
private fun SquiggleBackgroundLargePreview() {

core/xr/src/main/java/com/android/developers/androidify/xr/SpatialComponents.kt

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,19 @@
1515
*/
1616
package com.android.developers.androidify.xr
1717

18+
import androidx.annotation.DrawableRes
19+
import androidx.compose.foundation.Image
20+
import androidx.compose.foundation.layout.Box
21+
import androidx.compose.foundation.layout.fillMaxSize
1822
import androidx.compose.runtime.Composable
23+
import androidx.compose.ui.Modifier
24+
import androidx.compose.ui.graphics.vector.ImageVector
25+
import androidx.compose.ui.graphics.vector.rememberVectorPainter
26+
import androidx.compose.ui.layout.ContentScale
27+
import androidx.compose.ui.res.vectorResource
28+
import androidx.compose.ui.tooling.preview.Devices.PIXEL_TABLET
29+
import androidx.compose.ui.tooling.preview.Preview
30+
import androidx.compose.ui.unit.Dp
1931
import androidx.compose.ui.unit.dp
2032
import androidx.xr.compose.spatial.Subspace
2133
import androidx.xr.compose.subspace.SpatialBox
@@ -24,11 +36,13 @@ import androidx.xr.compose.subspace.SpatialPanel
2436
import androidx.xr.compose.subspace.SubspaceComposable
2537
import androidx.xr.compose.subspace.layout.SubspaceModifier
2638
import androidx.xr.compose.subspace.layout.aspectRatio
39+
import androidx.xr.compose.subspace.layout.fillMaxSize
2740
import androidx.xr.compose.subspace.layout.fillMaxWidth
2841
import androidx.xr.compose.subspace.layout.movable
2942
import androidx.xr.compose.subspace.layout.offset
3043
import androidx.xr.compose.subspace.layout.resizable
31-
import com.android.developers.androidify.theme.components.SquiggleBackgroundFull
44+
import androidx.xr.compose.unit.DpVolumeSize
45+
import com.android.developers.androidify.theme.AndroidifyTheme
3246

3347
/**
3448
* A composable for a Subspace with a Squiggle background.
@@ -37,6 +51,24 @@ import com.android.developers.androidify.theme.components.SquiggleBackgroundFull
3751
*/
3852
@Composable
3953
fun SquiggleBackgroundSubspace(
54+
minimumHeight: Dp,
55+
content:
56+
@SubspaceComposable @Composable
57+
SpatialBoxScope.() -> Unit,
58+
) {
59+
BackgroundSubspace(
60+
aspectRatio = 1.7f,
61+
drawable = R.drawable.squiggle_full,
62+
minimumHeight = minimumHeight,
63+
content = content,
64+
)
65+
}
66+
67+
@Composable
68+
fun BackgroundSubspace(
69+
aspectRatio: Float,
70+
@DrawableRes drawable: Int,
71+
minimumHeight: Dp,
4072
content:
4173
@SubspaceComposable @Composable
4274
SpatialBoxScope.() -> Unit,
@@ -45,14 +77,42 @@ fun SquiggleBackgroundSubspace(
4577
SpatialPanel(
4678
SubspaceModifier
4779
.movable()
48-
.resizable()
49-
.fillMaxWidth(1f)
50-
.aspectRatio(1.7f),
80+
.resizable(
81+
minimumSize = DpVolumeSize(0.dp, minimumHeight, 0.dp),
82+
maintainAspectRatio = true,
83+
)
84+
.fillMaxWidth()
85+
.aspectRatio(aspectRatio),
5186
) {
52-
SquiggleBackgroundFull()
87+
FillBackground(drawable)
5388
Subspace {
54-
SpatialBox(SubspaceModifier.offset(z = 10.dp), content = content)
89+
SpatialBox(SubspaceModifier.offset(z = 10.dp).fillMaxSize(), content = content)
5590
}
5691
}
5792
}
5893
}
94+
95+
/**
96+
* Background squiggle that tries to fit in its parent.
97+
*/
98+
@Composable
99+
fun FillBackground(@DrawableRes drawable: Int) {
100+
val vectorBackground =
101+
rememberVectorPainter(ImageVector.vectorResource(drawable))
102+
Box(modifier = Modifier.fillMaxSize()) {
103+
Image(
104+
painter = vectorBackground,
105+
contentDescription = null,
106+
modifier = Modifier.fillMaxSize(),
107+
contentScale = ContentScale.Fit,
108+
)
109+
}
110+
}
111+
112+
@Preview(device = PIXEL_TABLET)
113+
@Composable
114+
fun SquiggleFullImagePreview() {
115+
AndroidifyTheme {
116+
FillBackground(R.drawable.squiggle_full)
117+
}
118+
}

feature/creation/src/androidTest/java/com/android/developers/androidify/creation/CreationScreenTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ class CreationScreenTest {
303303

304304
composeTestRule.setContent {
305305
SharedElementContextPreview {
306-
LoadingScreen(onCancelPress = {})
306+
LoadingScreen(onCancelPress = {}, layoutType = EditScreenLayoutType.Medium)
307307
}
308308
}
309309

feature/creation/src/main/java/com/android/developers/androidify/creation/CreationScreen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ fun CreationScreen(
9999
onCancelPress = {
100100
creationViewModel.cancelInProgressTask()
101101
},
102+
layoutType = layoutType,
102103
)
103104
}
104105
}

feature/creation/src/main/java/com/android/developers/androidify/creation/LoadingScreen.kt

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import androidx.compose.runtime.setValue
4848
import androidx.compose.ui.Alignment
4949
import androidx.compose.ui.Modifier
5050
import androidx.compose.ui.draw.paint
51+
import androidx.compose.ui.graphics.Color
5152
import androidx.compose.ui.graphics.SolidColor
5253
import androidx.compose.ui.graphics.StrokeCap
5354
import androidx.compose.ui.graphics.graphicsLayer
@@ -70,25 +71,48 @@ import androidx.compose.ui.tooling.preview.Devices.PIXEL_3A_XL
7071
import androidx.compose.ui.tooling.preview.Preview
7172
import androidx.compose.ui.tooling.preview.PreviewScreenSizes
7273
import androidx.compose.ui.unit.dp
74+
import com.android.developers.androidify.creation.xr.LoadingScreenSpatial
7375
import com.android.developers.androidify.theme.AndroidifyTheme
7476
import com.android.developers.androidify.theme.components.AndroidifyTopAppBar
7577
import com.android.developers.androidify.theme.components.PrimaryButton
7678
import com.android.developers.androidify.util.LargeScreensPreview
7779
import com.android.developers.androidify.util.SmallPhonePreview
78-
import com.android.developers.androidify.util.isAtLeastMedium
7980
import kotlinx.coroutines.delay
8081
import kotlin.math.roundToInt
8182
import com.android.developers.androidify.creation.R as CreationR
8283

8384
@Composable
8485
fun LoadingScreen(
8586
onCancelPress: () -> Unit,
86-
isMediumScreen: Boolean = isAtLeastMedium(),
87+
layoutType: EditScreenLayoutType,
88+
) {
89+
when (layoutType) {
90+
EditScreenLayoutType.Spatial ->
91+
LoadingScreenSpatial(
92+
onCancelPress = onCancelPress,
93+
)
94+
95+
EditScreenLayoutType.Compact, EditScreenLayoutType.Medium ->
96+
LoadingScreenScaffold(
97+
topBar = {
98+
AndroidifyTopAppBar(isMediumWindowSize = layoutType == EditScreenLayoutType.Medium)
99+
},
100+
onCancelPress = onCancelPress,
101+
) { contentPadding ->
102+
LoadingScreenContents(contentPadding)
103+
}
104+
}
105+
}
106+
107+
@Composable
108+
fun LoadingScreenScaffold(
109+
topBar: @Composable () -> Unit,
110+
onCancelPress: () -> Unit,
111+
containerColor: Color = MaterialTheme.colorScheme.secondary,
112+
content: @Composable (PaddingValues) -> Unit,
87113
) {
88114
Scaffold(
89-
topBar = {
90-
AndroidifyTopAppBar(isMediumWindowSize = isMediumScreen)
91-
},
115+
topBar = topBar,
92116
bottomBar = {
93117
Box(
94118
modifier = Modifier
@@ -105,19 +129,16 @@ fun LoadingScreen(
105129
)
106130
}
107131
},
108-
containerColor = MaterialTheme.colorScheme.secondary,
132+
containerColor = containerColor,
109133
modifier = Modifier
110134
.fillMaxSize()
111135
.keepScreenOn(),
112-
) { contentPadding ->
113-
LoadingScreenContents(contentPadding)
114-
}
136+
content = content,
137+
)
115138
}
116139

117140
@Composable
118-
private fun LoadingScreenContents(
119-
contentPadding: PaddingValues,
120-
) {
141+
fun LoadingScreenContents(contentPadding: PaddingValues) {
121142
Column(
122143
modifier = Modifier
123144
.fillMaxSize()
@@ -202,7 +223,7 @@ private fun BoxScope.DecorativeSparkleDarkGreen(modifier: Modifier = Modifier) {
202223
@Composable
203224
fun LoadingScreenLargePreview() {
204225
AndroidifyTheme {
205-
LoadingScreen(onCancelPress = {})
226+
LoadingScreen(onCancelPress = {}, layoutType = EditScreenLayoutType.Medium)
206227
}
207228
}
208229

@@ -212,7 +233,7 @@ fun LoadingScreenLargePreview() {
212233
@Composable
213234
fun LoadingScreenPreview() {
214235
AndroidifyTheme {
215-
LoadingScreen(onCancelPress = {}, isMediumScreen = false)
236+
LoadingScreen(onCancelPress = {}, layoutType = EditScreenLayoutType.Compact)
216237
}
217238
}
218239

feature/creation/src/main/java/com/android/developers/androidify/creation/xr/EditScreenSpatial.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ fun EditScreenSpatial(
7575
onDropCallback: (Uri) -> Unit = {},
7676
) {
7777
DisableSharedTransition {
78-
SquiggleBackgroundSubspace {
78+
SquiggleBackgroundSubspace(minimumHeight = 600.dp) {
7979
MainPanelWorkaround()
8080
SpatialColumn(SubspaceModifier.fillMaxWidth()) {
8181
SpatialPanel(
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.android.developers.androidify.creation.xr
17+
18+
import androidx.compose.foundation.layout.Box
19+
import androidx.compose.foundation.layout.fillMaxHeight
20+
import androidx.compose.foundation.layout.fillMaxWidth
21+
import androidx.compose.foundation.layout.padding
22+
import androidx.compose.foundation.layout.size
23+
import androidx.compose.material3.IconButtonDefaults
24+
import androidx.compose.material3.MaterialTheme
25+
import androidx.compose.runtime.Composable
26+
import androidx.compose.ui.Alignment
27+
import androidx.compose.ui.Modifier
28+
import androidx.compose.ui.graphics.Color
29+
import androidx.compose.ui.unit.dp
30+
import androidx.xr.compose.spatial.ContentEdge
31+
import androidx.xr.compose.spatial.Orbiter
32+
import androidx.xr.compose.spatial.OrbiterOffsetType
33+
import androidx.xr.compose.subspace.SpatialPanel
34+
import androidx.xr.compose.subspace.layout.SubspaceModifier
35+
import androidx.xr.compose.subspace.layout.fillMaxHeight
36+
import androidx.xr.compose.subspace.layout.fillMaxWidth
37+
import androidx.xr.compose.subspace.layout.offset
38+
import com.android.developers.androidify.creation.LoadingScreenContents
39+
import com.android.developers.androidify.creation.LoadingScreenScaffold
40+
import com.android.developers.androidify.theme.AndroidifyTheme
41+
import com.android.developers.androidify.util.TabletPreview
42+
import com.android.developers.androidify.xr.BackgroundSubspace
43+
import com.android.developers.androidify.xr.FillBackground
44+
import com.android.developers.androidify.xr.MainPanelWorkaround
45+
import com.android.developers.androidify.xr.RequestHomeSpaceIconButton
46+
import com.android.developers.androidify.creation.R as CreationR
47+
48+
private const val squiggleSafeContentWidth = 0.4f
49+
private const val squiggleSafeContentHeight = 0.6f
50+
51+
@Composable
52+
fun LoadingScreenSpatial(
53+
onCancelPress: () -> Unit,
54+
) {
55+
BackgroundSubspace(
56+
aspectRatio = 1.4f,
57+
minimumHeight = 500.dp,
58+
drawable = CreationR.drawable.squiggle_light,
59+
) {
60+
MainPanelWorkaround()
61+
Orbiter(
62+
position = ContentEdge.Top,
63+
offsetType = OrbiterOffsetType.OuterEdge,
64+
offset = 32.dp,
65+
alignment = Alignment.End,
66+
) {
67+
RequestHomeSpaceIconButton(
68+
modifier = Modifier
69+
.size(64.dp, 64.dp)
70+
.padding(8.dp),
71+
colors = IconButtonDefaults.iconButtonColors(
72+
containerColor = MaterialTheme.colorScheme.secondaryContainer,
73+
),
74+
)
75+
}
76+
SpatialPanel(
77+
SubspaceModifier
78+
.fillMaxWidth(squiggleSafeContentWidth)
79+
.fillMaxHeight(squiggleSafeContentHeight)
80+
.offset(z = 10.dp),
81+
) {
82+
LoadingScreenScaffold(
83+
topBar = {},
84+
onCancelPress = onCancelPress,
85+
containerColor = Color.Transparent,
86+
) { contentPadding ->
87+
LoadingScreenContents(contentPadding)
88+
}
89+
}
90+
}
91+
}
92+
93+
@TabletPreview
94+
@Composable
95+
private fun LoadingScreenSpatialPreview() {
96+
AndroidifyTheme {
97+
Box {
98+
FillBackground(CreationR.drawable.squiggle_light)
99+
Box(
100+
Modifier
101+
.fillMaxHeight(squiggleSafeContentHeight)
102+
.fillMaxWidth(squiggleSafeContentWidth)
103+
.align(Alignment.Center),
104+
) {
105+
LoadingScreenScaffold(
106+
topBar = {},
107+
onCancelPress = { },
108+
containerColor = Color.Transparent,
109+
) { contentPadding ->
110+
LoadingScreenContents(contentPadding)
111+
}
112+
}
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)