flutter如何生成骨架屏

在Flutter中如何实现骨架屏效果?最近在开发一个需要加载数据的页面,想添加骨架屏提升用户体验。有没有推荐的第三方库或实现方案?最好能支持动态调整占位区域和动画效果,求大神分享具体实现方法或代码示例!

2 回复

Flutter中生成骨架屏可使用shimmer库。步骤如下:

  1. 添加shimmer依赖;
  2. 用Shimmer包裹组件;
  3. 设置渐变效果和基础布局。

示例代码:

Shimmer.fromColors(
  baseColor: Colors.grey[300],
  highlightColor: Colors.grey[100],
  child: Container(...),
)

更多关于flutter如何生成骨架屏的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在 Flutter 中生成骨架屏(Skeleton Screen)可以通过多种方式实现,以下是常见的方法和示例代码:

1. 使用 shimmer 库(推荐)

安装依赖:

dependencies:
  shimmer: ^2.0.0

示例代码:

import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';

class SkeletonScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Shimmer.fromColors(
        baseColor: Colors.grey[300]!,
        highlightColor: Colors.grey[100]!,
        child: ListView.builder(
          itemCount: 5,
          itemBuilder: (_, __) => Padding(
            padding: EdgeInsets.all(8.0),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  width: 48.0,
                  height: 48.0,
                  color: Colors.white,
                ),
                SizedBox(width: 16),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Container(
                        width: double.infinity,
                        height: 8.0,
                        color: Colors.white,
                      ),
                      SizedBox(height: 8),
                      Container(
                        width: double.infinity,
                        height: 8.0,
                        color: Colors.white,
                      ),
                    ],
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

2. 自定义骨架屏组件

class SkeletonItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(vertical: 8),
      child: Row(
        children: [
          Container(
            width: 60,
            height: 60,
            decoration: BoxDecoration(
              color: Colors.grey[300],
              borderRadius: BorderRadius.circular(8),
            ),
          ),
          SizedBox(width: 16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  width: double.infinity,
                  height: 12,
                  decoration: BoxDecoration(
                    color: Colors.grey[300],
                    borderRadius: BorderRadius.circular(4),
                  ),
                ),
                SizedBox(height: 8),
                Container(
                  width: MediaQuery.of(context).size.width * 0.5,
                  height: 10,
                  decoration: BoxDecoration(
                    color: Colors.grey[300],
                    borderRadius: BorderRadius.circular(4),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

使用建议:

  1. 在数据加载前显示骨架屏
  2. 使用 Visibility 或条件渲染控制显示/隐藏
  3. 骨架屏布局应与实际内容布局保持一致
  4. 可配合 AnimatedOpacity 实现平滑过渡

切换示例:

bool isLoading = true;

// 在build方法中
isLoading 
  ? SkeletonScreen()
  : YourActualContent();

这种方法能有效提升用户体验,让用户感知内容正在加载中。

回到顶部