MotionLayout自定义一个动画开关按钮
MotionLayout是一个非常新的类,它来自ConstraintLayout 2.0库中,主要意图是为了协助Android开发人员在应用中下降使用手势和组件动画的难度
使用方法
MotionSwitch(Modifier.height(26.dp).width(86.dp), onText = "最热", offText = "最新", onEvent = {
}, offEvent = {
})
完整代码直接拿去用
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.constraintlayout.compose.ConstraintSet
import androidx.constraintlayout.compose.ExperimentalMotionApi
import androidx.constraintlayout.compose.MotionLayout
import kotlin.math.roundToInt
/**
* @Description:
* @Author: JIULANG
* @Data: 2022/11/6 16:27
*/
@ExperimentalMotionApi
@Composable
fun MotionSwitch(
modifier:Modifier =Modifier,
check:Boolean =false,
onText:String = "on",
offText:String = "off",
onEvent :()-> Unit,
offEvent :()-> Unit,
) {
var animateToEnd by remember { mutableStateOf(check) }
val progress by animateFloatAsState(
targetValue = if (animateToEnd) 1f else 0f,
animationSpec = tween(1000)
)
var buttonSwitchHight by remember { mutableStateOf(IntSize(0, 0)) }
Column() {
MotionLayout(
ConstraintSet(
""" {
backgroundSwitch: {
custom: {
color: "#d2d2d2"
}
},
buttonSwitch: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0]
},
on: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
},
off: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
}
}"""
),
ConstraintSet(
""" {
backgroundSwitch: {
custom: {
color: "#343434"
}
},
buttonSwitch: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0]
},
on: {
top: ['backgroundSwitch', 'top', 0],
start: ['backgroundSwitch', 'start', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
},
off: {
top: ['backgroundSwitch', 'top', 0],
end: ['backgroundSwitch', 'end', 0],
bottom: ['backgroundSwitch', 'bottom', 0]
}
}"""
),
progress = progress,
modifier =modifier
) {
Box(
modifier = modifier
.layoutId("backgroundSwitch")
.clip(RoundedCornerShape(36.dp))
.onSizeChanged {
buttonSwitchHight = it
}
.clickable(onClick = {
if (animateToEnd){
onEvent.invoke()
}else{
offEvent.invoke()
}
animateToEnd = !animateToEnd })
.background(motionProperties("backgroundSwitch").value.color("color"))
)
Box(
modifier = Modifier
.height(buttonSwitchHight.height.dp)
.width((buttonSwitchHight.width/5).dp)
.layoutId("buttonSwitch")
.clip(RoundedCornerShape(36.dp))
.background(Color.Gray)
)
Text(
text = onText,
modifier = Modifier
.layoutId("on")
.width((buttonSwitchHight.width/5).dp),
color = Color.White,
fontSize = 12.sp,
textAlign = TextAlign.Center
)
Text(
text = offText,
modifier = Modifier
.layoutId("off")
.width((buttonSwitchHight.width/5).dp),
color = Color.White,
fontSize = 12.sp,
textAlign = TextAlign.Center
)
}
}
}