您可以创建随进度更改右侧的形状,并将一个长方体剪裁在另一个长方体之上.
结果
实施
@Composable
private fun BeforeAfterLayout(
modifier: Modifier = Modifier,
progress: Float,
beforeLayout: @Composable BoxScope.() -> Unit,
afterLayout: @Composable BoxScope.() -> Unit
) {
val shape = remember(progress) {
GenericShape { size: Size, layoutDirection: LayoutDirection ->
addRect(
rect = Rect(
topLeft = Offset.Zero,
bottomRight = Offset(size.width * progress, size.height)
)
)
}
}
Box(modifier) {
beforeLayout()
Box(
modifier = Modifier.clip(shape)
) {
afterLayout()
}
}
}
演示
@Preview
@Composable
private fun BeforeAfterTest() {
val infiniteTransition = rememberInfiniteTransition("before-after")
val progress by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(2000, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
),
label = "before-after"
)
Column(
modifier = Modifier.padding(20.dp)
) {
BeforeAfterLayout(
modifier = Modifier.size(240.dp).border(2.dp, Color.Red),
progress = progress,
beforeLayout = {
Image(
modifier = Modifier.fillMaxSize(),
painter = painterResource(R.drawable.avatar_1_raster),
contentDescription = null,
contentScale = ContentScale.FillBounds
)
},
afterLayout = {
Image(
modifier = Modifier.fillMaxSize(),
painter = painterResource(R.drawable.avatar_5_raster),
contentDescription = null,
contentScale = ContentScale.FillBounds
)
}
)
BeforeAfterLayout(
progress = progress,
beforeLayout = {
Button(
modifier = Modifier.width(150.dp),
onClick = {}
) {
Text("Before Button")
}
},
afterLayout = {
Button(
modifier = Modifier.width(150.dp),
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Green
),
onClick = {}
) {
Text("After Button")
}
}
)
}
}
第二种方法是使用BlendMode.Clear,并将lambda中的进度传递给动画,并将其重组为
@Composable
private fun BeforeAfterLayoutWithBlendMode(
modifier: Modifier = Modifier,
progress: () -> Float,
beforeLayout: @Composable BoxScope.() -> Unit,
afterLayout: @Composable BoxScope.() -> Unit
) {
Box(modifier) {
beforeLayout()
Box(
modifier = Modifier
.graphicsLayer {
compositingStrategy = CompositingStrategy.Offscreen
}
.drawWithContent {
drawContent()
drawRect(
color = Color.Transparent,
size = Size(size.width * (1 - progress()), size.height),
blendMode = BlendMode.Clear
)
}
) {
afterLayout()
}
}
}
另一种方法是,如果它只是你想要画的图像,在画布上画2个图像,然后改变第二个drawImage
函数的dstOffset
.
也可作为具有许多定制选项的库使用.