-
Notifications
You must be signed in to change notification settings - Fork 174
MotionLayout based Collapsing toolbar
John Hoford edited this page Oct 5, 2022
·
3 revisions
This is an example of how to use MotionLayout to create a collapsing toolbar
swipe.mp4
This is an example of how to use Compose MotionLayout as a Collapsing toolbar.
- s = remberScrollState() - to access the scrolling value
- Column(Modifier.verticalScroll(s)) - provide the scrolling list
- Spacer() - pad the start of the list
- Text() - after the padding
- MotionLayout( progress=s.value/(open_height-close_height)) - motionLayout to setup
- Composable being animated
@OptIn(ExperimentalMotionApi::class)
@Preview(group = "scroll", device = "spec:shape=Normal,width=480,height=800,unit=dp,dpi=440")
@Composable
fun ScrollText() {
val scroll = rememberScrollState(0)
var scene = """
{
ConstraintSets: {
start: {
title: {
bottom: ['image', 'bottom', 16],
start: [ 'image','start', 16],
},
image: {
width: 'parent',
height: 250,
top: ['parent', 'top', 0],
custom: {
cover: '#000000FF'
}
},
icon: {
top: ['image', 'top', 16],
start: [ 'image','start', 16],
alpha: 0,
},
},
end: {
title: {
centerVertically: 'image',
start: ['icon', 'end', 0],
scaleX: 0.7,
scaleY: 0.7,
},
image: {
width: 'parent',
height: 50,
top: ['parent', 'top', 0],
custom: {
cover: '#FF0000FF'
}
},
icon: {
top: ['image', 'top', 16],
start: [ 'image','start', 16],
},
},
},
Transitions: {
default: {
from: 'start',
to: 'end',
pathMotionArc: 'startHorizontal',
},
},
}
"""
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.verticalScroll(scroll)
) {
Spacer(Modifier.height(250.dp))
repeat(5) {
Text(
text = LoremIpsum(222).values.first(),
modifier = Modifier
.background(Color.White)
.padding(16.dp)
)
}
}
val progress = min(scroll.value / (3f * (250 - 50)), 1f);
MotionLayout(
modifier = Modifier.fillMaxSize(),
motionScene = MotionScene(content = scene),
progress = min((scroll.value) / 600f, 1f)
) {
Image(
modifier = Modifier.layoutId("image"),
painter = painterResource(R.drawable.bridge),
contentDescription = null,
contentScale = ContentScale.Crop
)
Box(modifier = Modifier
.layoutId("image")
.background(motionProperties("image").value.color("cover"))) {
}
Image(
modifier = Modifier.layoutId("icon"),
painter = painterResource(R.drawable.menu),
contentDescription = null
)
Text(
modifier = Modifier.layoutId("title"),
text = "San Francisco",
fontSize = 30.sp,
color = Color.White
)
}
}
@Composable
fun ScrollTextDSL() {
val scroll = rememberScrollState(0)
val big = 250.dp
val small = 50.dp
var scene = MotionScene() {
val start1 = constraintSet {
val title = createRefFor("title")
val image = createRefFor("image")
val icon = createRefFor("icon")
constrain(title) {
bottom.linkTo(image.bottom)
start.linkTo(image.start)
}
constrain(image) {
width = Dimension.matchParent
height = Dimension.value(big)
top.linkTo(parent.top)
customColor("cover", Color(0x000000FF))
}
constrain(icon) {
top.linkTo(image.top, 16.dp)
start.linkTo(image.start, 16.dp)
alpha = 0f
}
}
val end1 = constraintSet {
val title = createRefFor("title")
val image = createRefFor("image")
val icon = createRefFor("icon")
constrain(title) {
bottom.linkTo(image.bottom)
start.linkTo(icon.end)
centerVerticallyTo(image)
scaleX = 0.7f
scaleY = 0.7f
}
constrain(image) {
width = Dimension.matchParent
height = Dimension.value(small)
top.linkTo(parent.top)
customColor("cover", Color(0xFF0000FF))
}
constrain(icon) {
top.linkTo(image.top, 16.dp)
start.linkTo(image.start, 16.dp)
}
}
transition("default", start1, end1) {}
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.verticalScroll(scroll)
) {
Spacer(Modifier.height(big))
repeat(5) {
Text(
text = LoremIpsum(222).values.first(),
modifier = Modifier
.background(Color.White)
.padding(16.dp)
)
}
}
val gap = with(LocalDensity.current){big.toPx() - small.toPx()}
val progress = min(scroll.value / gap, 1f);
MotionLayout(
modifier = Modifier.fillMaxSize(),
motionScene = scene,
progress = progress
) {
Image(
modifier = Modifier.layoutId("image"),
painter = painterResource(R.drawable.bridge),
contentDescription = null,
contentScale = ContentScale.Crop
)
Box(modifier = Modifier
.layoutId("image")
.background(motionProperties("image").value.color("cover"))) {
}
Image(
modifier = Modifier.layoutId("icon"),
painter = painterResource(R.drawable.menu),
contentDescription = null
)
Text(
modifier = Modifier.layoutId("title"),
text = "San Francisco",
fontSize = 30.sp,
color = Color.White
)
}
}