MotionLayout存在于constraintlayout包中,使用前需要先添加依赖。
implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.0'
查看源码,可以看到MotionLayout的定义:
inline fun MotionLayout(
start: ConstraintSet,
end: ConstraintSet,
transition: androidx.constraintlayout.compose.Transition? = null,
progress: Float,
debug: EnumSet<MotionLayoutDebugFlags> = EnumSet.of(MotionLayoutDebugFlags.NONE),
modifier: Modifier = Modifier,
optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
crossinline content: @Composable MotionLayoutScope.() -> Unit
) {
MotionLayout(
start = start,
end = end,
transition = transition,
progress = progress,
debug = debug,
informationReceiver = null,
modifier = modifier,
optimizationLevel = optimizationLevel,
content = content
)
}
使用时必须要传的参数有:开始和结束的ConstraintSet、progress、content。
1.使用json来构建ConstraintSet:
//用于控制动画的开启
var animateButton by remember { mutableStateOf(false) }
val buttonAnimationProgress by animateFloatAsState(
targetValue = if (animateButton) 1f else 0f,
animationSpec = tween(1000)
)
Spacer(modifier = Modifier.height(16.dp))
MotionLayout(
ConstraintSet(
""" {
button1: {
width: "spread",
height: 60,
start: ['parent', 'start', 16],
end: ['parent', 'end', 16],
top: ['parent', 'top', 16]
},
button2: {
width: "spread",
height: 60,
start: ['parent', 'start', 16],
end: ['parent', 'end', 16],
top: ['button1', 'bottom', 16]
},
button3: {
width: "spread",
height: 60,
start: ['parent', 'start', 16],
end: ['parent', 'end', 16],
top: ['button2', 'bottom', 16]
}
} """
),
ConstraintSet(
""" {
button1: {
width: 100,
height: 60,
start: ['parent', 'start', 16],
end: ['button2', 'start', 16]
},
button2: {
width: 100,
height: 60,
start: ['button1', 'end', 16],
end: ['button2', 'start', 16]
},
button3: {
width: 100,
height: 60,
start: ['button2', 'end', 16],
end: ['parent', 'end', 16]
}
} """
),
progress = buttonAnimationProgress,
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
Button(
onClick = { animateButton = !animateButton },
modifier = Modifier.layoutId("button1")
) {
Text(text = "按钮一")
}
Button(
onClick = { animateButton = !animateButton },
modifier = Modifier.layoutId("button2")
) {
Text(text = "按钮二")
}
Button(
onClick = { animateButton = !animateButton },
modifier = Modifier.layoutId("button3")
) {
Text(text = "按钮三")
}
}
2.不使用json构建ConstraintSet的方式:
MotionLayout(
ConstraintSet {
val btn4 = createRefFor("btn4")
val btn5 = createRefFor("btn5")
val btn6 = createRefFor("btn6")
constrain(btn4) {
width = Dimension.matchParent
linkTo(
start = parent.start,
top = parent.top,
end = parent.end,
bottom = btn5.top,
topMargin = 4.dp,
bottomMargin = 4.dp,
startMargin = 16.dp,
endMargin = 16.dp
)
}
constrain(btn5) {
width = Dimension.matchParent
linkTo(
start = parent.start,
top = btn4.bottom,
end = parent.end,
bottom = btn6.top,
topMargin = 4.dp,
bottomMargin = 4.dp,
startMargin = 16.dp,
endMargin = 16.dp
)
}
constrain(btn6) {
width = Dimension.matchParent
linkTo(
start = parent.start,
top = btn5.bottom,
end = parent.end,
bottom = parent.bottom,
topMargin = 4.dp,
bottomMargin = 4.dp,
startMargin = 16.dp,
endMargin = 16.dp
)
}
},
ConstraintSet {
val btn4 = createRefFor("btn4")
val btn5 = createRefFor("btn5")
val btn6 = createRefFor("btn6")
constrain(btn4) {
width = Dimension.preferredWrapContent
height = Dimension.wrapContent
top.linkTo(parent.top, 8.dp)
bottom.linkTo(parent.bottom, 8.dp)
absoluteLeft.linkTo(parent.absoluteLeft, 16.dp)
absoluteRight.linkTo(btn5.absoluteLeft, 4.dp)
}
constrain(btn5) {
width = Dimension.preferredWrapContent
height = Dimension.wrapContent
top.linkTo(parent.top, 8.dp)
bottom.linkTo(parent.bottom, 8.dp)
absoluteLeft.linkTo(btn4.absoluteRight, 4.dp)
absoluteRight.linkTo(btn6.absoluteLeft, 4.dp)
}
constrain(btn6) {
width = Dimension.preferredWrapContent
height = Dimension.wrapContent
top.linkTo(parent.top, 8.dp)
bottom.linkTo(parent.bottom, 8.dp)
absoluteLeft.linkTo(btn5.absoluteRight, 4.dp)
absoluteRight.linkTo(parent.absoluteRight, 16.dp)
}
},
progress = buttonAnimationProgress,
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
Button(
onClick = { animateButton = !animateButton },
modifier = Modifier.layoutId("btn4")
) {
Text(text = "按钮四")
}
Button(
onClick = { animateButton = !animateButton },
modifier = Modifier.layoutId("btn5")
) {
Text(text = "按钮五")
}
Button(
onClick = { animateButton = !animateButton },
modifier = Modifier.layoutId("btn6")
) {
Text(text = "按钮六")
}
}
另一个例子:
var animateImage by remember { mutableStateOf(false) }
val imageAnimationProgress by animateFloatAsState(
targetValue = if (animateImage) 1f else 0f,
animationSpec = tween(1000)
)
MotionLayout(
ConstraintSet(
""" {
image1: {
width: 150,
height: 150,
start: ['parent', 'start', 16]
},
image2: {
width: 150,
height: 150,
start: ['parent', 'start', 32]
},
image3: {
width: 150,
height: 150,
start: ['parent', 'start', 48]
},
image4: {
width: 150,
height: 150,
start: ['parent', 'start', 64]
}
} """
),
ConstraintSet(
""" {
image1: {
width: 150,
height: 150,
start: ['parent', 'start', 16]
},
image2: {
width: 150,
height: 150,
start: ['image1', 'end', 16]
},
image3: {
width: 150,
height: 150,
start: ['parent', 'start', 16],
top: ['image1', 'bottom', 16]
},
image4: {
width: 150,
height: 150,
start: ['image1', 'end', 16],
top: ['image1', 'bottom', 16]
}
} """
),
progress = imageAnimationProgress,
modifier = Modifier
.fillMaxSize()
) {
Image(
painter = painterResource(id = R.mipmap.ic_sds_01),
contentDescription = "",
modifier = Modifier
.layoutId("image1")
.clickable { animateImage = !animateImage })
Image(
painter = painterResource(id = R.mipmap.ic_sds_02),
contentDescription = "",
modifier = Modifier
.layoutId("image2")
.clickable { animateImage = !animateImage })
Image(
painter = painterResource(id = R.mipmap.ic_sds_03),
contentDescription = "",
modifier = Modifier
.layoutId("image3")
.clickable { animateImage = !animateImage })
Image(
painter = painterResource(id = R.mipmap.ic_sds_04),
contentDescription = "",
modifier = Modifier
.layoutId("image4")
.clickable { animateImage = !animateImage })
}
本文暂时没有评论,来添加一个吧(●'◡'●)