Skip to content

Commit 74458e9

Browse files
committed
Add feathered edges to the quotes in the Spatial layout
1 parent 5865aab commit 74458e9

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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.results.xr
17+
18+
import androidx.compose.foundation.background
19+
import androidx.compose.foundation.basicMarquee
20+
import androidx.compose.foundation.layout.Box
21+
import androidx.compose.foundation.layout.fillMaxSize
22+
import androidx.compose.foundation.layout.size
23+
import androidx.compose.material3.Text
24+
import androidx.compose.runtime.Composable
25+
import androidx.compose.ui.Alignment
26+
import androidx.compose.ui.Modifier
27+
import androidx.compose.ui.draw.drawWithContent
28+
import androidx.compose.ui.geometry.Offset
29+
import androidx.compose.ui.geometry.Size
30+
import androidx.compose.ui.graphics.BlendMode
31+
import androidx.compose.ui.graphics.Brush
32+
import androidx.compose.ui.graphics.Color
33+
import androidx.compose.ui.graphics.CompositingStrategy
34+
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
35+
import androidx.compose.ui.graphics.graphicsLayer
36+
import androidx.compose.ui.tooling.preview.Preview
37+
import androidx.compose.ui.unit.DpSize
38+
import androidx.compose.ui.unit.dp
39+
import com.android.developers.androidify.theme.Primary
40+
41+
/**
42+
* Applies an edge feathering effect to the [ContentDrawScope].
43+
*
44+
* This behavior is a little incorrect around the corners, which have alpha transparency applied
45+
* twice over the area that is affected by the horizontal and vertical rectangles.
46+
*/
47+
fun ContentDrawScope.featheredEdges(edgeSize: Size) {
48+
drawContent()
49+
50+
drawRect(
51+
topLeft = Offset(0f, 0f),
52+
size = Size(edgeSize.width, size.height),
53+
brush =
54+
Brush.horizontalGradient(
55+
colors = listOf(Color.Transparent, Color.Black),
56+
startX = 0f,
57+
endX = edgeSize.width,
58+
),
59+
blendMode = BlendMode.DstIn,
60+
)
61+
drawRect(
62+
topLeft = Offset(size.width - edgeSize.width, 0f),
63+
size = Size(edgeSize.width, size.height),
64+
brush =
65+
Brush.horizontalGradient(
66+
colors = listOf(Color.Transparent, Color.Black),
67+
startX = size.width,
68+
endX = size.width - edgeSize.width,
69+
),
70+
blendMode = BlendMode.DstIn,
71+
)
72+
73+
drawRect(
74+
topLeft = Offset(0f, 0f),
75+
size = Size(size.width, edgeSize.height),
76+
brush =
77+
Brush.verticalGradient(
78+
colors = listOf(Color.Transparent, Color.Black),
79+
startY = 0f,
80+
endY = edgeSize.height,
81+
),
82+
blendMode = BlendMode.DstIn,
83+
)
84+
85+
drawRect(
86+
topLeft = Offset(0f, size.height - edgeSize.height),
87+
size = Size(size.width, edgeSize.height),
88+
brush =
89+
Brush.verticalGradient(
90+
colors = listOf(Color.Transparent, Color.Black),
91+
startY = size.width,
92+
endY = size.width - edgeSize.height,
93+
),
94+
blendMode = BlendMode.DstIn,
95+
)
96+
}
97+
98+
fun Modifier.featheredEdges(edgeSize: DpSize) = graphicsLayer {
99+
compositingStrategy = CompositingStrategy.Offscreen
100+
}.drawWithContent { featheredEdges(edgeSize.toSize()) }
101+
102+
/**
103+
* Feathers the edges.
104+
*
105+
* The size is expressed between [0, 1], where 0 represents 0 feathering,
106+
* and 1 represents a full feathering from edge to edge.
107+
*/
108+
fun Modifier.featheredEdges(edgeSizeFraction: Size) = graphicsLayer {
109+
compositingStrategy = CompositingStrategy.Offscreen
110+
}.drawWithContent {
111+
featheredEdges(Size(size.width * edgeSizeFraction.width, size.height * edgeSizeFraction.height))
112+
}
113+
114+
@Preview
115+
@Composable
116+
private fun FeatheredEdgePreview() {
117+
Box(
118+
Modifier
119+
.size(200.dp)
120+
.background(Primary)
121+
.featheredEdges(DpSize(10.dp, 10.dp)),
122+
) {
123+
}
124+
}
125+
126+
@Preview
127+
@Composable
128+
private fun FeatheredEdgeAnimatedPreview() {
129+
Box(
130+
Modifier
131+
.size(200.dp)
132+
.background(Primary),
133+
) {
134+
Box(
135+
Modifier
136+
.featheredEdges(DpSize(100.dp, 0.dp))
137+
.fillMaxSize(),
138+
) {
139+
Text(
140+
modifier = Modifier
141+
.align(Alignment.Center)
142+
.basicMarquee(Int.MAX_VALUE),
143+
text = "Test marquee with feathered edges!",
144+
maxLines = 1,
145+
)
146+
}
147+
}
148+
}

feature/results/src/main/java/com/android/developers/androidify/results/xr/ResultsScreenSpatial.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import androidx.compose.runtime.remember
2727
import androidx.compose.runtime.setValue
2828
import androidx.compose.ui.Alignment
2929
import androidx.compose.ui.Modifier
30+
import androidx.compose.ui.geometry.Size
3031
import androidx.compose.ui.graphics.Color
3132
import androidx.compose.ui.platform.LocalDensity
3233
import androidx.compose.ui.unit.dp
@@ -68,7 +69,7 @@ fun ResultsScreenSpatial(
6869
.fillMaxWidth()
6970
.fillMaxHeight(0.35f),
7071
) {
71-
backgroundQuotes(Modifier)
72+
backgroundQuotes(Modifier.featheredEdges(Size(0.1f, 0f)))
7273
}
7374
SpatialBox(SubspaceModifier.fillMaxWidth(0.6f)) {
7475
BackgroundSubspace(

0 commit comments

Comments
 (0)