Flutter占位符加载插件skeletons_forked的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter占位符加载插件skeletons_forked的使用

skeletons_forked 是一个用于构建自定义骨架小部件(Skeleton Widgets)的 Flutter 包,可以在页面加载时模仿页面布局。

示例

以下是 skeletons_forked 插件的一些示例图:

Items Paragraphs ListView (Default)
items paragraphs listview_default
ListView (Custom) ListView (Complex Cards) SkeletonTheme
listview_custom listview_cards skeleton_theme
Light/Dark modes Right-To-Left Custom Shimmer
light_dark_modes rtl custom_shimmer

所有示例可以在这里找到:https://github.com/Guihgo/skeletons_forked/tree/master/example/lib/examples

如何使用

Skeleton 小部件可以通过包裹子小部件来使用:

import 'package:skeletons_forked/skeletons_forked.dart';

Skeleton(
  isLoading: _isLoading,
  skeleton: SkeletonListView(),
  child: Container(
    child: Center(
      child: Text("Content"),
    ),
  ),
)

或者直接使用:

Container(
  child: _isLoading 
    ? SkeletonListView() 
    : Container(
        child: Center(
          child: Text("Content"),
        ),
      ),
)

还可以通过 SkeletonTheme 设置默认配置:

SkeletonTheme(
  shimmerGradient: LinearGradient(
    colors: [
      Color(0xFFD8E3E7),
      Color(0xFFC8D5DA),
      Color(0xFFD8E3E7),
    ],
    stops: [
      0.1,
      0.5,
      0.9,
    ],
  ),
  darkShimmerGradient: LinearGradient(
    colors: [
      Color(0xFF222222),
      Color(0xFF242424),
      Color(0xFF2B2B2B),
      Color(0xFF242424),
      Color(0xFF222222),
    ],
    stops: [
      0.0,
      0.2,
      0.5,
      0.8,
      1,
    ],
    begin: Alignment(-2.4, -0.2),
    end: Alignment(2.4, 0.2),
    tileMode: TileMode.clamp,
  ),
  child: MaterialApp(
    ...
  ),
)

更多定制化

对于更复杂的形状,可以在 SkeletonItem 小部件内构建你的骨架:

ListView.builder(
  physics: NeverScrollableScrollPhysics(),
  itemCount: 5,
  itemBuilder: (context, index) => Padding(
    padding: const EdgeInsets.all(8.0),
    child: Container(
      padding: const EdgeInsets.all(8.0),
      decoration: BoxDecoration(color: Colors.white),
      child: SkeletonItem(
        child: Column(
          children: [
            Row(
              children: [
                SkeletonAvatar(
                  style: SkeletonAvatarStyle(
                      shape: BoxShape.circle, width: 50, height: 50),
                ),
                SizedBox(width: 8),
                Expanded(
                  child: SkeletonParagraph(
                    style: SkeletonParagraphStyle(
                        lines: 3,
                        spacing: 6,
                        lineStyle: SkeletonLineStyle(
                          randomLength: true,
                          height: 10,
                          borderRadius: BorderRadius.circular(8),
                          minLength: MediaQuery.of(context).size.width / 6,
                          maxLength: MediaQuery.of(context).size.width / 3,
                        )),
                  ),
                )
              ],
            ),
            SizedBox(height: 12),
            SkeletonParagraph(
              style: SkeletonParagraphStyle(
                  lines: 3,
                  spacing: 6,
                  lineStyle: SkeletonLineStyle(
                    randomLength: true,
                    height: 10,
                    borderRadius: BorderRadius.circular(8),
                    minLength: MediaQuery.of(context).size.width / 2,
                  )),
            ),
            SizedBox(height: 12),
            SkeletonAvatar(
              style: SkeletonAvatarStyle(
                width: double.infinity,
                minHeight: MediaQuery.of(context).size.height / 8,
                maxHeight: MediaQuery.of(context).size.height / 3,
              ),
            ),
            SizedBox(height: 8),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Row(
                  children: [
                    SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
                    SizedBox(width: 8),
                    SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
                    SizedBox(width: 8),
                    SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
                  ],
                ),
                SkeletonLine(
                  style: SkeletonLineStyle(
                      height: 16,
                      width: 64,
                      borderRadius: BorderRadius.circular(8)),
                )
              ],
            )
          ],
        ),
      ),
    ),
  ),
);

更多关于Flutter占位符加载插件skeletons_forked的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter占位符加载插件skeletons_forked的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用skeletons_forked插件来实现占位符加载效果的代码案例。skeletons_forked是一个流行的Flutter插件,用于在数据加载时显示占位符动画,以提升用户体验。

首先,你需要在你的pubspec.yaml文件中添加对skeletons_forked的依赖:

dependencies:
  flutter:
    sdk: flutter
  skeletons_forked: ^2.0.0  # 请检查最新版本号并替换

然后运行flutter pub get来安装依赖。

接下来是一个简单的示例,展示如何在Flutter中使用skeletons_forked插件:

import 'package:flutter/material.dart';
import 'package:skeletons_forked/skeletons_forked.dart';
import 'dart:async';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Skeletons Forked Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isLoading = true;
  List<String> data = [];

  @override
  void initState() {
    super.initState();
    Timer(Duration(seconds: 2), () {
      setState(() {
        isLoading = false;
        data = List.generate(20, (index) => "Item $index");
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Skeletons Forked Demo'),
      ),
      body: isLoading
          ? SkeletonListBuilder(
              itemCount: 20,
              builder: (context, index) {
                return SkeletonItem(
                  width: double.infinity,
                  height: 50,
                  margin: EdgeInsets.only(bottom: 10),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      SkeletonCircleAvatar(radius: 25),
                      SizedBox(width: 10),
                      Expanded(
                        child: Skeleton(
                          width: double.infinity,
                          height: 25,
                          child: Text(""),
                        ),
                      ),
                    ],
                  ),
                );
              },
            )
          : ListView.builder(
              itemCount: data.length,
              itemBuilder: (context, index) {
                return ListTile(
                  leading: CircleAvatar(
                    child: Text(data[index][0]),
                  ),
                  title: Text(data[index]),
                );
              },
            ),
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 安装依赖:在pubspec.yaml文件中添加skeletons_forked依赖。
  2. 创建主应用:在MyApp类中定义了一个基本的Flutter应用。
  3. 创建主页:在MyHomePage类中定义了一个带有状态(isLoadingdata)的页面。
  4. 模拟数据加载:在initState方法中,使用Timer模拟了一个异步数据加载过程。
  5. 构建UI:在build方法中,根据isLoading状态显示占位符列表或真实数据列表。
    • isLoadingtrue时,显示占位符列表,使用SkeletonListBuilderSkeletonItem来创建占位符。
    • isLoadingfalse时,显示真实数据列表,使用ListView.builder来创建列表项。

这样,你就可以在你的Flutter应用中使用skeletons_forked插件来显示占位符加载动画了。

回到顶部