返回

Android Skeleton Screen Placeholder Loading Effect (Part 1)

Android

骨架屏:提升安卓应用用户体验的必备技巧(第 1 部分)

概述

在当今快节奏的数字世界中,用户期望移动应用提供无缝且响应迅速的体验。骨架屏,又称加载骨架屏或占位符屏,已成为一项必不可少的技术,它可在从服务器或数据库获取实际内容时,通过显示临时占位符来增强用户体验。

本系列文章共分为两部分,深入探讨在 Android 应用程序中实现骨架屏占位符加载效果的方法。在第一部分,我们将重点关注单个视图和 RecyclerView 的核心概念和实现技术。

理解骨架屏

骨架屏本质上是轻量级布局,它们模仿实际界面的结构和内容,即使在尚未获取真实数据时,也能让人瞥见应用程序的功能。它们通常由方框、矩形和圆圈组成,代表各种 UI 元素,如图像、文本、按钮和列表。

骨架屏的主要目的是:

  • 通过提供即时反馈和减少感知加载时间来增强用户体验
  • 防止用户与未填充的 UI 元素交互,确保流程顺畅
  • 通过延迟实际内容的渲染,直到必需时才渲染,从而提升应用程序性能

实现方法

有几种方法可以在 Android 应用程序中实现骨架屏占位符加载效果:

  • 创建自定义视图: 创建模仿所需 UI 元素的自定义视图,并在必要时动态加载这些视图。
  • 第三方库: 利用现成的库,如 Shimmer、Skeleton 和 Placeholder,它们提供开箱即用的骨架屏实现。

第 1 部分:单个视图和 RecyclerView

为单个视图实现骨架屏

对于单个视图,如按钮、文本字段和图像,我们可以创建扩展相应基本视图并覆盖 onDraw() 方法以绘制骨架形状的自定义视图。以下代码片段演示如何创建自定义骨架按钮:

public class SkeletonButton extends Button {

    private Paint skeletonPaint;

    public SkeletonButton(Context context) {
        super(context);
        initSkeletonPaint();
    }

    public SkeletonButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSkeletonPaint();
    }

    public SkeletonButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initSkeletonPaint();
    }

    private void initSkeletonPaint() {
        skeletonPaint = new Paint();
        skeletonPaint.setColor(Color.LTGRAY);
        skeletonPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        canvas.drawRoundRect(0, 0, width, height, 10, 10, skeletonPaint);
    }
}

为 RecyclerView 实现骨架屏

对于 RecyclerView,我们可以创建一个项目装饰,将骨架视图绘制在列表项上方。以下代码片段演示如何创建骨架项目装饰:

public class SkeletonItemDecoration extends RecyclerView.ItemDecoration {

    private Paint skeletonPaint;

    public SkeletonItemDecoration() {
        skeletonPaint = new Paint();
        skeletonPaint.setColor(Color.LTGRAY);
        skeletonPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);

        // 遍历 RecyclerView 中的可见视图
        for (int i = 0; i < parent.getChildCount(); i++) {
            View view = parent.getChildAt(i);

            // 计算视图的边界
            Rect bounds = new Rect();
            view.getGlobalVisibleRect(bounds);

            // 绘制骨架视图
            int width = bounds.width();
            int height = bounds.height();
            c.drawRoundRect(bounds, 10, 10, skeletonPaint);
        }
    }
}

若要将骨架项目装饰应用于 RecyclerView,请将以下行添加到布局中:

<androidx.recyclerview.widget.RecyclerView
    ...
    app:skeletonItemDecoration="@{skeletonItemDecoration}" />

结论

在本文中,我们探讨了骨架屏占位符加载效果的概念,并讨论了各种实现方法。我们提供了关于如何使用自定义视图和项目装饰为单个视图和 RecyclerView 实现骨架屏的详细说明。

在本系列的下一部分中,我们将深入探讨高级技术,包括内存优化、支持嵌套布局以及动态处理数据更改。我们还将讨论在 Android 应用程序中使用骨架屏的局限性和最佳实践。

常见问题解答

  1. 什么是骨架屏?
    骨架屏是轻量级布局,模仿实际界面的结构和内容,即使在尚未获取真实数据时,也能让人瞥见应用程序的功能。

  2. 为什么使用骨架屏很重要?
    骨架屏可增强用户体验、防止用户与未填充的 UI 元素交互,并通过延迟实际内容的渲染,直到必需时才渲染,从而提升应用程序性能。

  3. 如何为单个视图实现骨架屏?
    创建扩展相应基本视图并覆盖 onDraw() 方法以绘制骨架形状的自定义视图。

  4. 如何为 RecyclerView 实现骨架屏?
    创建一个项目装饰,将骨架视图绘制在列表项上方。

  5. 使用骨架屏时有哪些局限性?
    骨架屏可能无法完美匹配实际内容,并且在处理复杂布局时可能会存在性能问题。