安卓Compose实现鱼骨加载中效果

安卓Compose实现鱼骨加载中效果

文章目录

本文首发地址 https://h89.cn/archives/404.html

背景与简介

在移动应用开发中,加载中占位动画(Skeleton/骨架屏)能够有效提升用户体验,减少因数据延迟带来的焦虑感。鱼骨加载效果是一种常见的骨架屏动画,模拟内容结构,配合闪烁动画(Shimmer)让界面在数据加载时更具活力。Jetpack Compose 作为 Android 现代声明式UI框架,极大简化了骨架屏实现难度。

适用场景

  • 网络请求数据加载时的占位
  • 列表、卡片等内容结构明确的页面
  • 需要提升加载体验的场景

Compose骨架屏与传统View实现对比

  • 传统View实现骨架屏通常需要自定义View、手动绘制、管理动画,代码复杂且维护成本高。
  • Compose下,借助第三方库如 compose-shimmer,仅需简单修饰符组合即可实现灵活的骨架屏动画,代码更简洁、可读性更强。

Shimmer动画原理简介

Shimmer是一种通过渐变色块横向移动,模拟光影流动的动画效果。其本质是利用Canvas绘制渐变蒙版,并通过属性动画不断平移,实现闪烁流动的视觉效果。compose-shimmer库对这一过程进行了高度封装,开发者只需一行Modifier即可应用。

安卓如何实现如下图类似鱼骨加载中效果

我们需要使用compose-shimmer,添加依赖 (build.gradle)
implementation("com.valentinilk.shimmer:compose-shimmer:1.3.2")

最新的版本号可以参见 https://github.com/valentinilk/compose-shimmer

定义一个状态类 UiState 用于管理加载状态和数据:

kotlin 复制代码
data class UiState(
    val isLoading: Boolean = true, // 控制是否处于加载状态
    val data: List<Order> = emptyList() // 实际数据列表
) : IState

UiState 包含了 isLoading 布尔值来指示当前是否正在加载数据,以及 data 列表来存储实际的订单数据。当 isLoading 为 true 时,UI 将显示占位符(鱼骨效果),否则显示实际数据。

在 LazyColumn 中根据 UiState 的 isLoading 状态来显示不同的内容:

当 isLoading 为 true 时,我们渲染固定数量的占位符(这里是5个),并传入空的字符串作为占位内容。这些占位符将通过 OrderItemView 应用鱼骨加载效果。

当 isLoading 为 false 时,我们渲染实际的 viewState.data 中的数据。

kotlin 复制代码
LazyColumn(
    modifier = Modifier.padding(horizontal = 16.dp),
    verticalArrangement = Arrangement.spacedBy(16.dp)
) {
    if (viewState.isLoading) {
        items(5) { index ->
            // 传入空的字符占位
            OrderItemView(
                order = Order(
                    type = "              ",
                    status = "          ",
                    time = "                                   ",
                    startAddress = "                                        ",
                    endAddress = "                                         "
                ),
                viewState = viewState
            )
        }
    } else {
        items(viewState.data.size) { index ->
            OrderItemView(
                order = viewState.data[index],
                viewState = viewState
            )
        }
    }
}

OrderItemView 的部分参考实现如下:

OrderItemView 是一个可组合函数,它根据 viewState.isLoading 的值来决定是显示鱼骨加载效果还是实际的订单信息。关键在于 Modifier.shimmer() 的应用。

kotlin 复制代码
@Composable
fun OrderItemView(order: Order, viewState: UiState) {
    // 通过 viewState.isLoading 控制显示
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 10.dp)
            .then(if (viewState.isLoading) Modifier.shimmer() else Modifier),
        shape = RoundedCornerShape(16.dp),
        elevation = CardDefaults.cardElevation(4.dp),
        colors = CardDefaults.cardColors(containerColor = Color.White)
    ) {
        // 部分实现, 通过 viewState.isLoading 控制显示
            Text(
                modifier = Modifier
                    .background(
                        color = if (viewState.isLoading) Color.LightGray else Color.Transparent,
                        shape = RoundedCornerShape(2.dp)
                    )
                    .then(if (viewState.isLoading) Modifier.shimmer() else Modifier), // shimmer 作用在 Text 上,使其背景闪烁
                text = order.type,
                style = MaterialTheme.typography.titleMedium
            )
    }
}

常见问题与优化建议

  • 闪烁效果不明显?
    • 请确保 Modifier.shimmer() 应用在 background 等绘制修饰符之后。
    • 可调整骨架色(如 Color.LightGray)和Shimmer参数(如高亮色、动画速度)增强对比度。
  • 骨架屏与内容跳变明显?
    • 建议骨架屏布局与实际内容布局保持一致,避免切换时界面抖动。
  • 性能影响?
    • compose-shimmer 性能较优,但大量骨架项或复杂动画时建议限制骨架数量,避免过度绘制。
  • 自定义骨架形状?
    • 可通过 background 的 shape 参数自定义圆角、椭圆等形状,灵活适配不同UI风格。

参考资料

相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui