This repository was archived by the owner on Dec 27, 2024. It is now read-only.
- Notifications
You must be signed in to change notification settings - Fork 172
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 ) } }