Skip to content

Commit ee796a9

Browse files
authored
Shared element snippets (#256)
* add shared element snippets * Apply Spotless * Split snippets into different files. * Apply Spotless --------- Co-authored-by: riggaroo <[email protected]>
1 parent 21a691c commit ee796a9

File tree

12 files changed

+1515
-0
lines changed

12 files changed

+1515
-0
lines changed

compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/BasicSharedElementSnippets.kt

Lines changed: 480 additions & 0 deletions
Large diffs are not rendered by default.

compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/CustomizeSharedElementsSnippets.kt

Lines changed: 562 additions & 0 deletions
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* Copyright 2024 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+
17+
@file:OptIn(ExperimentalSharedTransitionApi::class)
18+
19+
package com.example.compose.snippets.animations.sharedelement
20+
21+
import androidx.compose.animation.AnimatedContent
22+
import androidx.compose.animation.AnimatedVisibilityScope
23+
import androidx.compose.animation.ExperimentalSharedTransitionApi
24+
import androidx.compose.animation.SharedTransitionLayout
25+
import androidx.compose.animation.SharedTransitionScope
26+
import androidx.compose.animation.fadeIn
27+
import androidx.compose.animation.fadeOut
28+
import androidx.compose.foundation.Image
29+
import androidx.compose.foundation.background
30+
import androidx.compose.foundation.border
31+
import androidx.compose.foundation.clickable
32+
import androidx.compose.foundation.layout.Column
33+
import androidx.compose.foundation.layout.Row
34+
import androidx.compose.foundation.layout.padding
35+
import androidx.compose.foundation.layout.size
36+
import androidx.compose.foundation.shape.CircleShape
37+
import androidx.compose.foundation.shape.RoundedCornerShape
38+
import androidx.compose.material3.Text
39+
import androidx.compose.runtime.Composable
40+
import androidx.compose.runtime.getValue
41+
import androidx.compose.runtime.mutableStateOf
42+
import androidx.compose.runtime.remember
43+
import androidx.compose.runtime.setValue
44+
import androidx.compose.ui.Modifier
45+
import androidx.compose.ui.draw.clip
46+
import androidx.compose.ui.graphics.Color
47+
import androidx.compose.ui.layout.ContentScale
48+
import androidx.compose.ui.res.painterResource
49+
import androidx.compose.ui.tooling.preview.Preview
50+
import androidx.compose.ui.unit.dp
51+
import androidx.compose.ui.unit.sp
52+
import com.example.compose.snippets.R
53+
import com.example.compose.snippets.ui.theme.LavenderLight
54+
import com.example.compose.snippets.ui.theme.RoseLight
55+
56+
private class SharedElementBasicUsage4 {
57+
58+
@Preview
59+
@Composable
60+
private fun SharedElementApp() {
61+
var showDetails by remember {
62+
mutableStateOf(false)
63+
}
64+
SharedTransitionLayout {
65+
AnimatedContent(
66+
showDetails,
67+
label = "basic_transition"
68+
) { targetState ->
69+
if (!targetState) {
70+
MainContent(
71+
onShowDetails = {
72+
showDetails = true
73+
},
74+
animatedVisibilityScope = this@AnimatedContent,
75+
sharedTransitionScope = this@SharedTransitionLayout
76+
)
77+
} else {
78+
DetailsContent(
79+
onBack = {
80+
showDetails = false
81+
},
82+
animatedVisibilityScope = this@AnimatedContent,
83+
sharedTransitionScope = this@SharedTransitionLayout
84+
)
85+
}
86+
}
87+
}
88+
}
89+
90+
// [START android_compose_animations_shared_element_shared_bounds]
91+
@Composable
92+
private fun MainContent(
93+
onShowDetails: () -> Unit,
94+
modifier: Modifier = Modifier,
95+
sharedTransitionScope: SharedTransitionScope,
96+
animatedVisibilityScope: AnimatedVisibilityScope
97+
) {
98+
with(sharedTransitionScope) {
99+
Row(
100+
modifier = Modifier
101+
.padding(8.dp)
102+
.sharedBounds(
103+
rememberSharedContentState(key = "bounds"),
104+
animatedVisibilityScope = animatedVisibilityScope,
105+
enter = fadeIn(),
106+
exit = fadeOut()
107+
)
108+
// [START_EXCLUDE]
109+
.border(1.dp, Color.Gray.copy(alpha = 0.5f), RoundedCornerShape(8.dp))
110+
.background(LavenderLight, RoundedCornerShape(8.dp))
111+
.clickable {
112+
onShowDetails()
113+
}
114+
.padding(8.dp)
115+
// [END_EXCLUDE]
116+
) {
117+
// [START_EXCLUDE]
118+
Image(
119+
painter = painterResource(id = R.drawable.cupcake),
120+
contentDescription = "Cupcake",
121+
modifier = Modifier
122+
.sharedElement(
123+
rememberSharedContentState(key = "image"),
124+
animatedVisibilityScope = animatedVisibilityScope
125+
)
126+
.size(100.dp)
127+
.clip(CircleShape),
128+
contentScale = ContentScale.Crop
129+
)
130+
Text(
131+
"Cupcake", fontSize = 21.sp,
132+
modifier = Modifier.sharedBounds(
133+
rememberSharedContentState(key = "title"),
134+
animatedVisibilityScope = animatedVisibilityScope
135+
)
136+
)
137+
// [END_EXCLUDE]
138+
}
139+
}
140+
}
141+
142+
@Composable
143+
private fun DetailsContent(
144+
modifier: Modifier = Modifier,
145+
onBack: () -> Unit,
146+
sharedTransitionScope: SharedTransitionScope,
147+
animatedVisibilityScope: AnimatedVisibilityScope
148+
) {
149+
with(sharedTransitionScope) {
150+
Column(
151+
modifier = Modifier
152+
.sharedBounds(
153+
rememberSharedContentState(key = "bounds"),
154+
animatedVisibilityScope = animatedVisibilityScope,
155+
enter = fadeIn(),
156+
exit = fadeOut()
157+
)
158+
// [START_EXCLUDE]
159+
.padding(top = 200.dp, start = 16.dp, end = 16.dp)
160+
.border(1.dp, Color.Gray.copy(alpha = 0.5f), RoundedCornerShape(8.dp))
161+
.background(RoseLight, RoundedCornerShape(8.dp))
162+
.clickable {
163+
onBack()
164+
}
165+
.padding(8.dp)
166+
// [END_EXCLUDE]
167+
168+
) {
169+
// [START_EXCLUDE]
170+
Image(
171+
painter = painterResource(id = R.drawable.cupcake),
172+
contentDescription = "Cupcake",
173+
modifier = Modifier
174+
.sharedElement(
175+
rememberSharedContentState(key = "image"),
176+
animatedVisibilityScope = animatedVisibilityScope
177+
)
178+
.size(200.dp)
179+
.clip(CircleShape),
180+
contentScale = ContentScale.Crop
181+
)
182+
Text(
183+
"Cupcake", fontSize = 28.sp,
184+
modifier = Modifier.sharedBounds(
185+
rememberSharedContentState(key = "title"),
186+
animatedVisibilityScope = animatedVisibilityScope
187+
)
188+
)
189+
Text(
190+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet lobortis velit. " +
191+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit." +
192+
" Curabitur sagittis, lectus posuere imperdiet facilisis, nibh massa " +
193+
"molestie est, quis dapibus orci ligula non magna. Pellentesque rhoncus " +
194+
"hendrerit massa quis ultricies. Curabitur congue ullamcorper leo, at maximus"
195+
)
196+
// [END_EXCLUDE]
197+
}
198+
}
199+
}
200+
// [END android_compose_animations_shared_element_shared_bounds]
201+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2024 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+
17+
@file:OptIn(ExperimentalSharedTransitionApi::class)
18+
19+
package com.example.compose.snippets.animations.sharedelement
20+
21+
import androidx.annotation.DrawableRes
22+
import androidx.compose.animation.AnimatedVisibility
23+
import androidx.compose.animation.ExitTransition
24+
import androidx.compose.animation.ExperimentalSharedTransitionApi
25+
import androidx.compose.animation.SharedTransitionLayout
26+
import androidx.compose.animation.fadeIn
27+
import androidx.compose.animation.fadeOut
28+
import androidx.compose.foundation.layout.size
29+
import androidx.compose.foundation.layout.wrapContentWidth
30+
import androidx.compose.material3.Text
31+
import androidx.compose.runtime.Composable
32+
import androidx.compose.ui.Modifier
33+
import androidx.compose.ui.platform.LocalContext
34+
import androidx.compose.ui.platform.LocalInspectionMode
35+
import androidx.compose.ui.res.painterResource
36+
import androidx.compose.ui.tooling.preview.Preview
37+
import androidx.compose.ui.unit.dp
38+
import coil.compose.AsyncImage
39+
import coil.request.ImageRequest
40+
41+
@Preview
42+
@Composable
43+
private fun SharedAsyncImage() {
44+
SharedTransitionLayout {
45+
AnimatedVisibility(visible = true) {
46+
// [START android_compose_shared_element_async_image_tip]
47+
AsyncImage(
48+
model = ImageRequest.Builder(LocalContext.current)
49+
.data("your-image-url")
50+
.crossfade(true)
51+
.build(),
52+
placeholder = null,
53+
contentDescription = null,
54+
modifier = Modifier
55+
.size(120.dp)
56+
.sharedBounds(
57+
rememberSharedContentState(
58+
key = "image-key"
59+
),
60+
animatedVisibilityScope = this,
61+
exit = ExitTransition.None
62+
)
63+
)
64+
// [END android_compose_shared_element_async_image_tip]
65+
}
66+
}
67+
}
68+
69+
@Composable
70+
fun debugPlaceholder(@DrawableRes debugPreview: Int) =
71+
if (LocalInspectionMode.current) {
72+
painterResource(id = debugPreview)
73+
} else {
74+
null
75+
}
76+
77+
@Preview
78+
@Composable
79+
private fun SharedElementTypicalUseText() {
80+
SharedTransitionLayout {
81+
AnimatedVisibility(visible = true) {
82+
// [START android_compose_shared_element_text_tip]
83+
Text(
84+
text = "This is an example of how to share text",
85+
modifier = Modifier
86+
.wrapContentWidth()
87+
.sharedBounds(
88+
rememberSharedContentState(
89+
key = "shared Text"
90+
),
91+
animatedVisibilityScope = this,
92+
enter = fadeIn() + scaleInSharedContentToBounds(),
93+
exit = fadeOut() + scaleOutSharedContentToBounds()
94+
)
95+
)
96+
// [END android_compose_shared_element_text_tip]
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)