Skip to content
This repository was archived by the owner on Dec 9, 2024. It is now read-only.

Commit 47e2c2d

Browse files
committed
MotionCompose: Fade
Change-Id: I8a0ed832d4fab8c6a5bec324ea0716d0e09b34aa
1 parent 343a5b4 commit 47e2c2d

File tree

11 files changed

+227
-39
lines changed

11 files changed

+227
-39
lines changed

MotionCompose/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ All the source codes for demos are in the
2020
[demo](app/src/main/java/com/example/android/compose/motion/demo)
2121
package.
2222

23+
### [Layout > Fade](app/src/main/java/com/example/android/compose/motion/demo/fade)
24+
25+
https://user-images.githubusercontent.com/1237536/142575353-8ed5cc04-34e3-45ea-9782-19408c8d2c37.mp4
26+
2327
### [Layout > Fade through](app/src/main/java/com/example/android/compose/motion/demo/fadethrough)
2428

2529
https://user-images.githubusercontent.com/1237536/142538271-480a5573-4231-414a-88cd-9fd9951fc792.mp4
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (C) 2021 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+
* http://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+
package com.example.android.compose.motion.demo
18+
19+
import com.example.android.compose.motion.R
20+
21+
val CheeseImages = listOf(
22+
R.drawable.cheese_1,
23+
R.drawable.cheese_2,
24+
R.drawable.cheese_3,
25+
R.drawable.cheese_4,
26+
R.drawable.cheese_5
27+
)

MotionCompose/app/src/main/java/com/example/android/compose/motion/demo/Demo.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.example.android.compose.motion.demo
1818

1919
import androidx.compose.runtime.Composable
20+
import com.example.android.compose.motion.demo.fade.FadeDemo
2021
import com.example.android.compose.motion.demo.fadethrough.FadeThroughDemo
2122

2223
enum class Demo(
@@ -25,6 +26,19 @@ enum class Demo(
2526
val apis: List<String>,
2627
val content: @Composable () -> Unit
2728
) {
29+
Fade(
30+
title = "Layout > Fade",
31+
description = """
32+
A fade creates a smooth sequence between elements that fully overlap each other, such as
33+
photos inside of a card or another container. When a new element enters, it fades in
34+
over the current element.
35+
""".trimIndent().replace('\n', ' '),
36+
apis = listOf(
37+
"AnimatedContent"
38+
),
39+
content = { FadeDemo() }
40+
),
41+
2842
FadeThrough(
2943
title = "Layout > Fade through",
3044
description = """
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (C) 2021 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+
* http://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+
package com.example.android.compose.motion.demo
18+
19+
import androidx.compose.foundation.layout.Box
20+
import androidx.compose.foundation.layout.BoxScope
21+
import androidx.compose.foundation.layout.fillMaxSize
22+
import androidx.compose.foundation.layout.padding
23+
import androidx.compose.material3.ExperimentalMaterial3Api
24+
import androidx.compose.material3.Scaffold
25+
import androidx.compose.material3.SmallTopAppBar
26+
import androidx.compose.material3.Text
27+
import androidx.compose.runtime.Composable
28+
import androidx.compose.ui.Modifier
29+
import com.google.accompanist.insets.LocalWindowInsets
30+
import com.google.accompanist.insets.rememberInsetsPaddingValues
31+
32+
@OptIn(ExperimentalMaterial3Api::class)
33+
@Composable
34+
fun SimpleScaffold(
35+
title: String,
36+
modifier: Modifier = Modifier,
37+
content: @Composable BoxScope.() -> Unit
38+
) {
39+
Scaffold(
40+
topBar = {
41+
SmallTopAppBar(
42+
title = {
43+
Text(text = title)
44+
},
45+
modifier = Modifier
46+
.padding(
47+
rememberInsetsPaddingValues(
48+
insets = LocalWindowInsets.current.systemBars,
49+
applyBottom = false
50+
)
51+
)
52+
)
53+
},
54+
modifier = modifier
55+
) {
56+
Box(
57+
modifier = Modifier.fillMaxSize()
58+
) {
59+
content()
60+
}
61+
}
62+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (C) 2021 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+
* http://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+
package com.example.android.compose.motion.demo.fade
18+
19+
import androidx.compose.animation.AnimatedContent
20+
import androidx.compose.animation.AnimatedContentScope
21+
import androidx.compose.animation.ContentTransform
22+
import androidx.compose.animation.ExperimentalAnimationApi
23+
import androidx.compose.animation.core.LinearOutSlowInEasing
24+
import androidx.compose.animation.core.snap
25+
import androidx.compose.animation.core.tween
26+
import androidx.compose.animation.fadeIn
27+
import androidx.compose.animation.fadeOut
28+
import androidx.compose.foundation.Image
29+
import androidx.compose.foundation.layout.padding
30+
import androidx.compose.foundation.layout.size
31+
import androidx.compose.foundation.shape.RoundedCornerShape
32+
import androidx.compose.material3.Button
33+
import androidx.compose.material3.Text
34+
import androidx.compose.runtime.Composable
35+
import androidx.compose.runtime.getValue
36+
import androidx.compose.runtime.mutableStateOf
37+
import androidx.compose.runtime.remember
38+
import androidx.compose.runtime.setValue
39+
import androidx.compose.ui.Alignment
40+
import androidx.compose.ui.Modifier
41+
import androidx.compose.ui.draw.clip
42+
import androidx.compose.ui.layout.ContentScale
43+
import androidx.compose.ui.res.painterResource
44+
import androidx.compose.ui.unit.dp
45+
import com.example.android.compose.motion.demo.CheeseImages
46+
import com.example.android.compose.motion.demo.Demo
47+
import com.example.android.compose.motion.demo.SimpleScaffold
48+
49+
@OptIn(ExperimentalAnimationApi::class)
50+
@Composable
51+
fun FadeDemo() {
52+
SimpleScaffold(title = Demo.Fade.title) {
53+
54+
val painters = CheeseImages.map { painterResource(it) }
55+
var index by remember { mutableStateOf(0) }
56+
57+
AnimatedContent(
58+
targetState = index,
59+
modifier = Modifier.align(Alignment.Center),
60+
transitionSpec = fade()
61+
) { targetIndex ->
62+
Image(
63+
painter = painters[targetIndex],
64+
contentDescription = "Cheese",
65+
modifier = Modifier
66+
.size(256.dp, 192.dp)
67+
.clip(shape = RoundedCornerShape(16.dp)),
68+
contentScale = ContentScale.Crop
69+
)
70+
}
71+
72+
Button(
73+
onClick = { index = (index + 1) % painters.size },
74+
modifier = Modifier
75+
.align(Alignment.BottomCenter)
76+
.padding(64.dp)
77+
) {
78+
Text(text = "NEXT")
79+
}
80+
}
81+
}
82+
83+
/**
84+
* Creates a transitionSpec for configuring [AnimatedContent] to the fade pattern.
85+
*/
86+
@OptIn(ExperimentalAnimationApi::class)
87+
private fun fade(
88+
durationMillis: Int = 300
89+
): AnimatedContentScope<Int>.() -> ContentTransform {
90+
return {
91+
ContentTransform(
92+
// The initial content should stay until the target content is completely opaque.
93+
initialContentExit = fadeOut(animationSpec = snap(delayMillis = durationMillis)),
94+
// The target content fades in. This is shown on top of the initial content.
95+
targetContentEnter = fadeIn(
96+
animationSpec = tween(
97+
durationMillis = durationMillis,
98+
// LinearOutSlowInEasing is suitable for incoming elements.
99+
easing = LinearOutSlowInEasing
100+
)
101+
)
102+
)
103+
}
104+
}

MotionCompose/app/src/main/java/com/example/android/compose/motion/demo/fadethrough/FadeThroughDemo.kt

Lines changed: 14 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@ import androidx.compose.animation.fadeIn
2828
import androidx.compose.animation.fadeOut
2929
import androidx.compose.foundation.Image
3030
import androidx.compose.foundation.layout.Arrangement
31-
import androidx.compose.foundation.layout.Box
3231
import androidx.compose.foundation.layout.Column
3332
import androidx.compose.foundation.layout.IntrinsicSize
3433
import androidx.compose.foundation.layout.Row
3534
import androidx.compose.foundation.layout.Spacer
36-
import androidx.compose.foundation.layout.fillMaxSize
3735
import androidx.compose.foundation.layout.height
3836
import androidx.compose.foundation.layout.padding
3937
import androidx.compose.foundation.layout.size
@@ -48,8 +46,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
4846
import androidx.compose.material3.Icon
4947
import androidx.compose.material3.IconButton
5048
import androidx.compose.material3.MaterialTheme
51-
import androidx.compose.material3.Scaffold
52-
import androidx.compose.material3.SmallTopAppBar
5349
import androidx.compose.material3.Surface
5450
import androidx.compose.material3.Text
5551
import androidx.compose.material3.TextButton
@@ -69,46 +65,26 @@ import androidx.compose.ui.tooling.preview.Preview
6965
import androidx.compose.ui.unit.dp
7066
import com.example.android.compose.motion.R
7167
import com.example.android.compose.motion.demo.Demo
68+
import com.example.android.compose.motion.demo.SimpleScaffold
7269
import com.example.android.compose.motion.ui.MotionComposeTheme
73-
import com.google.accompanist.insets.LocalWindowInsets
74-
import com.google.accompanist.insets.rememberInsetsPaddingValues
7570

7671
@OptIn(ExperimentalMaterial3Api::class)
7772
@Composable
7873
fun FadeThroughDemo() {
79-
Scaffold(
80-
topBar = {
81-
SmallTopAppBar(
82-
title = {
83-
Text(text = Demo.FadeThrough.title)
84-
},
85-
modifier = Modifier
86-
.padding(
87-
rememberInsetsPaddingValues(
88-
insets = LocalWindowInsets.current.systemBars,
89-
applyBottom = false
90-
)
91-
)
92-
)
93-
},
94-
) {
95-
Box(
96-
modifier = Modifier.fillMaxSize()
97-
) {
98-
var expanded by rememberSaveable { mutableStateOf(false) }
99-
DemoCard(
100-
expanded = expanded,
101-
modifier = Modifier.align(Alignment.Center)
102-
)
74+
SimpleScaffold(title = Demo.FadeThrough.title) {
75+
var expanded by rememberSaveable { mutableStateOf(false) }
76+
DemoCard(
77+
expanded = expanded,
78+
modifier = Modifier.align(Alignment.Center)
79+
)
10380

104-
Button(
105-
onClick = { expanded = !expanded },
106-
modifier = Modifier
107-
.align(Alignment.BottomCenter)
108-
.padding(64.dp)
109-
) {
110-
Text(text = "TOGGLE")
111-
}
81+
Button(
82+
onClick = { expanded = !expanded },
83+
modifier = Modifier
84+
.align(Alignment.BottomCenter)
85+
.padding(64.dp)
86+
) {
87+
Text(text = "TOGGLE")
11288
}
11389
}
11490
}

MotionCompose/app/src/main/java/com/example/android/compose/motion/ui/home/Home.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ private fun DemoList(
8282
contentPadding = rememberInsetsPaddingValues(
8383
insets = LocalWindowInsets.current.systemBars,
8484
applyTop = false
85-
)
85+
),
86+
verticalArrangement = Arrangement.spacedBy(8.dp)
8687
) {
8788
items(items = Demo.values()) { demo ->
8889
DemoCard(
214 KB
Loading
181 KB
Loading
256 KB
Loading

0 commit comments

Comments
 (0)