本文讨论下如何在Jetpack Compose中实现一个Shimmer闪烁动画效果,而且不依赖任何第三方sdk库。
扩展函数
我们先定义一个扩展函数,用来实现闪烁效果:
fun Modifier.shimmerEffect(
widthOfShadowBrush: Int = 300,
endOfOffsetY: Float = 80f,
durationMillis: Int = 1000,
): Modifier = composed {
val shimmerColors = listOf(
// 1.
Color.Transparent,
Color.White.withAlpha(0.8f),
Color.White.withAlpha(0.7f),
Color.White.withAlpha(0.6f),
Color.White.withAlpha(0.5f),
Color.White.withAlpha(0.45f),
Color.White.withAlpha(0.5f),
Color.White.withAlpha(0.6f),
Color.White.withAlpha(0.7f),
Color.White.withAlpha(0.8f),
Color.Transparent,
)
val transition = rememberInfiniteTransition(label = "shimmerLoadingAnimation")
val configuration = LocalConfiguration.current
val density = LocalDensity.current
val width = with(density) { configuration.screenWidthDp.dp.toPx() }
val translateAnimation = transition.animateFloat(
// 2.
initialValue = 0f,
targetValue = width + 100f,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = durationMillis,
easing = LinearEasing,
),
repeatMode = RepeatMode.Restart,
),
label = "Shimmer loading animation",
)
this.background(
// 3.
brush = Brush.linearGradient(
colors = shimmerColors,
start = Offset(x = translateAnimation.value - widthOfShadowBrush, y = 0.0f),
end = Offset(x = translateAnimation.value, y = endOfOffsetY),
),
)
}
fun Color.withAlpha(alphaP: Float): Color = Color(red = this.red, green = this.green, blue = this.blue, alpha = alphaP)
第一步,定义一个渐变的颜色列表,具体的颜色是透明--百分比渐低透明-45%透明--百分比渐高透明--透明。
第二步,定义一个动画,这个动画有两个作用,一个是提供渐变色的start和end位置,即决定了渐变色的倾斜角度,第二个作用是是渐变色区域进行移动。
第三步,调用Brush的linearGradient函数。Brush的宽度是widthOfShadowBrush=300像素,另外一个参数endOfOffsetY=80像素决定了渐变色的水平倾斜角度。endOfOffsetY=0的话,水平倾斜角度为0即水平渐变300像素。endOfOffsetY越大,水平倾斜角度也越大。
demo使用
@Composable
fun LoadingShimmerEffect() {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = 20.dp, bottom = 20.dp)
.background(Color.Gray)
) {
repeat(1) {
Box(
modifier = Modifier
.width(100.dp)
.height(100.dp)
.padding(16.dp)
.shimmerEffect()
) {
Text(
modifier = Modifier
.matchParentSize()
.fillMaxWidth()
.fillMaxHeight()
.wrapContentSize(align = Alignment.Center),
text = "abcdefg",
color = Color.Black,
fontSize = 30.sp
)
}
}
repeat(1) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.padding(16.dp)
.shimmerEffect()
) {
Text(
modifier = Modifier
.matchParentSize()
.fillMaxWidth()
.fillMaxHeight()
.wrapContentSize(align = Alignment.Center),
text = "abcdefg",
color = Color.Black,
fontSize = 30.sp
)
}
}
}
}
可以看到,效果仅仅是在背景上做了个渐变的动画,的确是有点闪烁的效果,但是并没有facebook开源的shimmer闪烁动画效果好。
原文链接:
Shimmer animations in Jetpack Compose without extra dependencies