「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」
简单介绍
MotionLayout是constraintlayout2.0以后才有的功能。
MotionLayout
是ConstraintLayout
的子布局。专门用来实现运动过程中的控件动画
在Android中实现动画是一件复杂的事情。MotionLayout
的问世就是为了化繁为简
MotionLayout
是在Android中实现过渡的一种新的有效方法。 它充当布局过渡和复杂运动处理之间的桥梁,在属性动画框架 , TransitionManager和CoordinatorLayout之间提供了多种功能
MotionScence
作为动画布局中的根节点
ConstraintSet
用于布局ConstraintLayout子项的约束的不变描述
分为开始和结束
使用MotionLayout时要传入开始和结束的ConstraintSet
开始使用
首先导入依赖
//约束布局
implementation("androidx.constraintlayout:constraintlayout-compose:2.1.0")
写这篇文章时时2.1.0
效果图
首先在ConstraintSet里面定义一个layoutId-xxx 接着在Box引用layoutId
Box(
modifier = Modifier
.layoutId("xxx")
)
实现这个开关需要4个组件 两个Box和两个Text分别表示按钮背景和开关按钮还有Ligth、dark文本
先写ConstraintSet
按钮背景
开始的ConstraintSet
ConstraintSet(
""" {
//按钮背景
backgroundSwitch: {
start: ['parent', 'start', 36],
top: ['parent', 'top', 66],
end: ['parent', 'end', 36],
custom: {
color: "#d2d2d2"
}
},
)
结束的ConstraintSet
ConstraintSet(
""" {
backgroundSwitch: {
start: ['parent', 'start', 36],
top: ['parent', 'top', 66],
end: ['parent', 'end', 36],
custom: {
color: "#343434"
}
},
)
Box(
modifier = Modifier
.layoutId("backgroundSwitch")
.width(300.dp)
.height(72.dp)
.clip(RoundedCornerShape(36.dp))
.background(motionProperties("backgroundSwitch").value.color("color"))
)
按钮
开始的ConstraintSet
buttonSwitch: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0]
},
结束的ConstraintSet
buttonSwitch: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0]
},
文本
开始的ConstraintSet
light: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
},
dark: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
}
结束的ConstraintSet
light: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
},
dark: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
}
点击事件
var animateToEnd by remember { mutableStateOf(false) }
...
clickable(onClick = { animateToEnd = !animateToEnd })
MotionLayout动画
val progress by animateFloatAsState(
targetValue = if (animateToEnd) 1f else 0f,
animationSpec = tween(1000)//持续时间1秒
)
完整代码
@Composable
private fun MotionLayout2Example() {
var animateToEnd by remember { mutableStateOf(false) }
val progress by animateFloatAsState(
targetValue = if (animateToEnd) 1f else 0f,
animationSpec = tween(1000)
)
Column(Modifier.background(Color.White)) {
MotionLayout(
ConstraintSet(
""" {
backgroundSwitch: {
start: ['parent', 'start', 36],
top: ['parent', 'top', 66],
end: ['parent', 'end', 36],
custom: {
color: "#d2d2d2"
}
},
buttonSwitch: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0]
},
light: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
},
dark: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
}
}"""
),
ConstraintSet(
""" {
backgroundSwitch: {
start: ['parent', 'start', 36],
top: ['parent', 'top', 66],
end: ['parent', 'end', 36],
custom: {
color: "#343434"
}
},
buttonSwitch: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0]
},
light: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
},
dark: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
}
}"""
),
progress = progress,
modifier = Modifier
.fillMaxSize()
.background(Color.White)
) {
Box(
modifier = Modifier
.layoutId("backgroundSwitch")
.width(300.dp)
.height(72.dp)
.clip(RoundedCornerShape(36.dp))
.clickable(onClick = { animateToEnd = !animateToEnd })
.background(motionProperties("backgroundSwitch").value.color("color"))
)
Box(
modifier = Modifier
.layoutId("buttonSwitch")
.width(150.dp)
.height(72.dp)
.clip(RoundedCornerShape(36.dp))
.background(Color.Gray)
)
Text(
text = "light",
modifier = Modifier
.layoutId("light")
.width(150.dp),
color = Color.White,
fontSize = 24.sp,
textAlign = TextAlign.Center
)
Text(
text = "dark",
modifier = Modifier
.layoutId("dark")
.width(150.dp),
color = Color.Black,
fontSize = 24.sp,
textAlign = TextAlign.Center
)
}
}
}