Jetpack Compose框架下手搓一个Shimmer闪烁动画效果

本文讨论下如何在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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容