Flutter骨架屏加载插件g_skeleton的使用

Flutter骨架屏加载插件g_skeleton的使用

g_skeleton 是一个用于构建美观的骨架屏的小部件。通过使用该插件,你可以在数据加载时为用户提供一个动态的视觉反馈。

使用

示例代码

以下是一个完整的示例代码,展示了如何在Flutter应用中使用 g_skeleton 插件。

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

import 'package:g_skeleton/g_skeleton.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // 这个小部件是你的应用的根节点。
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Skeleton Demo',
        theme: ThemeData(
          // 应用的主题
          primarySwatch: Colors.blue,
        ),
        home: CupertinoTabScaffold(
            tabBar: CupertinoTabBar(
              items: [
                BottomNavigationBarItem(
                    icon: Icon(CupertinoIcons.home), label: 'home'),
                BottomNavigationBarItem(
                    icon: Icon(CupertinoIcons.settings), label: 'setting'),
              ],
            ),
            tabBuilder: (BuildContext context, int index) {
              return YoutubePage();
            }));
  }
}

class YoutubePage extends StatefulWidget {
  [@override](/user/override)
  _YoutubePageState createState() => _YoutubePageState();
}

class _YoutubePageState extends State<YoutubePage> {
  final controller = SkeletonController(end: CupertinoColors.activeOrange);

  [@override](/user/override)
  void initState() {
    super.initState();
    controller.start();

    Future.delayed(Duration(seconds: 20)).then((value) => controller.stop());
  }

  [@override](/user/override)
  void dispose() {
    super.dispose();
    controller.stop();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('Skeleton'),
      ),
      child: SafeArea(
        child: Column(
          children: <Widget>[
            _buildSkeletonItem(context),
            _buildSkeletonItem(context),
            Expanded(
              flex: 1,
              child: Skeleton(
                controller,
                builder: (context) => Container(
                  color: CupertinoColors.activeBlue,
                ),
                increasing: UniqueKey(),
              ),
            ),
            Container(
              height: 50,
              child: Skeleton(
                controller,
                increasing: UniqueKey(),
              ),
            )
          ],
        ),
      ),
    );
  }

  Widget _buildSkeletonItem(BuildContext context) {
    final increasing = UniqueKey();
    return Expanded(
      child: Column(
        children: <Widget>[
          Expanded(
            flex: 2,
            child: Skeleton(controller, increasing: increasing),
          ),
          Expanded(
            child: Container(
              color: CupertinoColors.white,
              child: Row(
                children: <Widget>[
                  Expanded(
                    flex: 1,
                    child: Container(
                      alignment: Alignment.center,
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(30),
                        child: SizedBox.fromSize(
                          size: Size(60, 60),
                          child: Skeleton(controller),
                        ),
                      ),
                    ),
                  ),
                  Expanded(
                    flex: 3,
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(8, 8, 8, 20),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Expanded(
                              flex: 2,
                              child: ClipRRect(
                                borderRadius: BorderRadius.circular(4),
                                child: Skeleton(controller, increasing: increasing),
                              )),
                          Spacer(),
                          Expanded(
                            flex: 2,
                            child: FractionallySizedBox(
                                widthFactor: 0.7,
                                child: ClipRRect(
                                  borderRadius: BorderRadius.circular(4),
                                  child: Skeleton(controller, increasing: increasing),
                                )),
                          ),
                          Spacer(),
                          Expanded(
                            flex: 2,
                            child: FractionallySizedBox(
                                widthFactor: 0.5,
                                child: ClipRRect(
                                  borderRadius: BorderRadius.circular(4),
                                  child: Skeleton(controller, increasing: increasing),
                                )),
                          )
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

说明

  • 导入包

    import 'package:g_skeleton/g_skeleton.dart';
    
  • 初始化控制器

    final controller = SkeletonController(end: CupertinoColors.activeOrange);
    

    控制器用于管理骨架屏的状态。

  • 开始和停止动画

    [@override](/user/override)
    void initState() {
      super.initState();
      controller.start();
    
      Future.delayed(Duration(seconds: 20)).then((value) => controller.stop());
    }
    

    在组件初始化时启动骨架屏动画,并在20秒后停止动画。

  • 构建骨架屏项

    Widget _buildSkeletonItem(BuildContext context) {
      final increasing = UniqueKey();
      return Expanded(
        child: Column(
          children: <Widget>[
            Expanded(
              flex: 2,
              child: Skeleton(controller, increasing: increasing),
            ),
            Expanded(
              child: Container(
                color: CupertinoColors.white,
                child: Row(
                  children: <Widget>[
                    Expanded(
                      flex: 1,
                      child: Container(
                        alignment: Alignment.center,
                        child: ClipRRect(
                          borderRadius: BorderRadius.circular(30),
                          child: SizedBox.fromSize(
                            size: Size(60, 60),
                            child: Skeleton(controller),
                          ),
                        ),
                      ),
                    ),
                    Expanded(
                      flex: 3,
                      child: Padding(
                        padding: const EdgeInsets.fromLTRB(8, 8, 8, 20),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            Expanded(
                                flex: 2,
                                child: ClipRRect(
                                  borderRadius: BorderRadius.circular(4),
                                  child: Skeleton(controller, increasing: increasing),
                                )),
                            Spacer(),
                            Expanded(
                              flex: 2,
                              child: FractionallySizedBox(
                                  widthFactor: 0.7,
                                  child: ClipRRect(
                                    borderRadius: BorderRadius.circular(4),
                                    child: Skeleton(controller, increasing: increasing),
                                  )),
                            ),
                            Spacer(),
                            Expanded(
                              flex: 2,
                              child: FractionallySizedBox(
                                  widthFactor: 0.5,
                                  child: ClipRRect(
                                    borderRadius: BorderRadius.circular(4),
                                    child: Skeleton(controller, increasing: increasing),
                                  )),
                            )
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      );
    }
    

更多关于Flutter骨架屏加载插件g_skeleton的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


在Flutter中,骨架屏(Skeleton Screen)是一种在数据加载时显示的占位符效果,它可以提升用户体验,让用户感知到内容正在加载。g_skeleton 是一个常用的Flutter骨架屏插件,它可以帮助开发者快速实现骨架屏效果。

1. 安装 g_skeleton

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

dependencies:
  flutter:
    sdk: flutter
  g_skeleton: ^最新版本

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

2. 基本使用

g_skeleton 提供了 SkeletonSkeletonContainer 等组件,可以方便地实现骨架屏效果。

2.1 使用 SkeletonContainer

SkeletonContainer 是一个简单的容器,可以在加载时显示骨架屏效果。

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

class SkeletonExample extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Skeleton Example'),
      ),
      body: ListView.builder(
        itemCount: 5,
        itemBuilder: (context, index) {
          return SkeletonContainer(
            child: ListTile(
              leading: CircleAvatar(),
              title: Text('Loading...'),
              subtitle: Text('Loading...'),
            ),
          );
        },
      ),
    );
  }
}

2.2 使用 Skeleton

Skeleton 是一个更灵活的组件,可以自定义骨架屏的样式。

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

class SkeletonExample extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Skeleton Example'),
      ),
      body: ListView.builder(
        itemCount: 5,
        itemBuilder: (context, index) {
          return ListTile(
            leading: Skeleton(
              width: 40,
              height: 40,
              radius: 20,
            ),
            title: Skeleton(
              width: double.infinity,
              height: 16,
            ),
            subtitle: Skeleton(
              width: double.infinity,
              height: 12,
            ),
          );
        },
      ),
    );
  }
}

3. 自定义骨架屏样式

g_skeleton 允许你自定义骨架屏的样式,比如颜色、圆角等。

Skeleton(
  width: 100,
  height: 100,
  color: Colors.grey[300],
  borderRadius: BorderRadius.circular(10),
)

4. 控制骨架屏的显示与隐藏

你可以通过 Skeletonshow 属性来控制骨架屏的显示与隐藏。

bool isLoading = true;

Skeleton(
  width: 100,
  height: 100,
  show: isLoading,
  child: Container(
    width: 100,
    height: 100,
    color: Colors.blue,
  ),
)

5. 完整示例

以下是一个完整的示例,展示了如何使用 g_skeleton 实现骨架屏效果。

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

class SkeletonExample extends StatefulWidget {
  [@override](/user/override)
  _SkeletonExampleState createState() => _SkeletonExampleState();
}

class _SkeletonExampleState extends State<SkeletonExample> {
  bool isLoading = true;

  [@override](/user/override)
  void initState() {
    super.initState();
    // 模拟数据加载
    Future.delayed(Duration(seconds: 3), () {
      setState(() {
        isLoading = false;
      });
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Skeleton Example'),
      ),
      body: ListView.builder(
        itemCount: 5,
        itemBuilder: (context, index) {
          return ListTile(
            leading: Skeleton(
              width: 40,
              height: 40,
              radius: 20,
              show: isLoading,
              child: CircleAvatar(
                backgroundColor: Colors.blue,
              ),
            ),
            title: Skeleton(
              width: double.infinity,
              height: 16,
              show: isLoading,
              child: Text('Loaded Title'),
            ),
            subtitle: Skeleton(
              width: double.infinity,
              height: 12,
              show: isLoading,
              child: Text('Loaded Subtitle'),
            ),
          );
        },
      ),
    );
  }
}

void main() => runApp(MaterialApp(
  home: SkeletonExample(),
));
回到顶部