Flutter占位骨架屏插件easy_skeleton的使用

Flutter占位骨架屏插件easy_skeleton的使用

在本教程中,我们将学习如何在Flutter项目中使用easy_skeleton插件来实现占位骨架屏。此插件可以帮助我们在网络请求或数据加载期间展示一个动态的占位屏幕,以提高用户体验。

安装

首先,在你的pubspec.yaml文件中添加easy_skeleton依赖:

dependencies:
  easy_skeleton: ^1.0.0

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

使用

接下来,我们将通过一个简单的示例来演示如何使用easy_skeleton插件。

示例代码

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Skeleton Demo',
      theme: ThemeData(primarySwatch: Colors.teal),
      darkTheme: ThemeData.dark(),
      themeMode: ThemeMode.system,
      builder: (_, child) {
        return SkeletonManager(
          viewMode: SkeletonViewMode.auto,
          theme: SkeletonThemeData(color: Colors.grey, radius: 4),
          // darkTheme: SkeletonThemeData(color: Colors.amber, radius: 4),
          // groupBuilder: (context, child) {
          //   final color = SkeletonTheme.of(context).color;
          //
          //   return Shimmer.fromColors(
          //     baseColor: color!,
          //     highlightColor: color.withOpacity(0.8),
          //     child: child,
          //   );
          // },
          child: child!,
        );
      },
      home: const SkeletonDemoPage(),
    );
  }
}

class InvertedTheme extends StatelessWidget {
  final Widget child;
  const InvertedTheme({Key? key, required this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var app = context.findAncestorWidgetOfExactType<MaterialApp>();
    if (app != null && app.theme != null && app.darkTheme != null) {
      var isDark = Theme.of(context).brightness == Brightness.dark;
      var brightness = isDark ? Brightness.light : Brightness.dark;
      var themeData = isDark ? app.theme : app.darkTheme;
      return Theme(
        data: themeData!.copyWith(brightness: brightness),
        child: child,
      );
    }
    return child;
  }
}

代码解释

  1. 导入库

    import 'package:easy_skeleton/easy_skeleton.dart';
    import 'package:flutter/material.dart';
    
  2. 主应用类

    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Skeleton Demo',
          theme: ThemeData(primarySwatch: Colors.teal),
          darkTheme: ThemeData.dark(),
          themeMode: ThemeMode.system,
          builder: (_, child) {
            return SkeletonManager(
              viewMode: SkeletonViewMode.auto,
              theme: SkeletonThemeData(color: Colors.grey, radius: 4),
              // darkTheme: SkeletonThemeData(color: Colors.amber, radius: 4),
              // groupBuilder: (context, child) {
              //   final color = SkeletonTheme.of(context).color;
              //
              //   return Shimmer.fromColors(
              //     baseColor: color!,
              //     highlightColor: color.withOpacity(0.8),
              //     child: child,
              //   );
              // },
              child: child!,
            );
          },
          home: const SkeletonDemoPage(),
        );
      }
    }
    
    • SkeletonManager 是用于管理骨架屏的核心组件。
    • viewMode 设置为 SkeletonViewMode.auto,表示根据当前主题自动选择骨架屏样式。
    • themedarkTheme 分别定义了默认主题和暗黑主题下的骨架屏颜色和圆角半径。
    • child 参数是实际的应用页面。
  3. 主题切换类

    class InvertedTheme extends StatelessWidget {
      final Widget child;
      const InvertedTheme({Key? key, required this.child}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        var app = context.findAncestorWidgetOfExactType<MaterialApp>();
        if (app != null && app.theme != null && app.darkTheme != null) {
          var isDark = Theme.of(context).brightness == Brightness.dark;
          var brightness = isDark ? Brightness.light : Brightness.dark;
          var themeData = isDark ? app.theme : app.darkTheme;
          return Theme(
            data: themeData!.copyWith(brightness: brightness),
            child: child,
          );
        }
        return child;
      }
    }
    

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用easy_skeleton插件来实现占位骨架屏效果的代码示例。easy_skeleton是一个流行的Flutter插件,用于在数据加载时显示占位骨架屏,从而提升用户体验。

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

dependencies:
  flutter:
    sdk: flutter
  easy_skeleton: ^x.y.z  # 请替换为最新版本号

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

接下来,我们来看一个具体的代码示例,展示如何使用easy_skeleton来实现占位骨架屏:

import 'package:flutter/material.dart';
import 'package:easy_skeleton/easy_skeleton.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

void main() {
  runApp(ProviderScope(child: MyApp()));
}

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

class MyHomePage extends HookWidget {
  final _controller = useState<bool>(true); // 控制骨架屏的显示

  @override
  Widget build(BuildContext context) {
    final isLoading = _controller.value;

    return Scaffold(
      appBar: AppBar(
        title: Text('Easy Skeleton Demo'),
      ),
      body: Center(
        child: isLoading
            ? SkeletonScreen(
                // 自定义骨架屏布局
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    SkeletonWidget(
                      width: double.infinity,
                      height: 50,
                      margin: EdgeInsets.symmetric(vertical: 10),
                    ),
                    SkeletonWidget(
                      width: double.infinity,
                      height: 20,
                      shape: BoxShape.circle,
                      margin: EdgeInsets.symmetric(vertical: 10),
                    ),
                    SkeletonWidget(
                      width: double.infinity,
                      height: 100,
                      margin: EdgeInsets.symmetric(vertical: 10),
                    ),
                  ],
                ),
              )
            : FutureBuilder<void>(
                future: _simulateDataLoading(),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return CircularProgressIndicator(); // 或者继续使用骨架屏
                  } else if (snapshot.hasError) {
                    return Text('Error: ${snapshot.error}');
                  } else {
                    return Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Text('Name: John Doe', style: TextStyle(fontSize: 24)),
                        SizedBox(height: 10),
                        CircleAvatar(
                          backgroundImage: NetworkImage('https://via.placeholder.com/150'),
                          radius: 30,
                        ),
                        SizedBox(height: 10),
                        Text('Description: A short description about John Doe.', style: TextStyle(fontSize: 16)),
                      ],
                    );
                  }
                },
              ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 切换骨架屏显示状态
          _controller.value = !_controller.value;
          // 重新触发数据加载模拟
          _simulateDataLoading();
        },
        tooltip: 'Toggle Skeleton',
        child: Icon(isLoading ? Icons.visibility_off : Icons.visibility),
      ),
    );
  }

  Future<void> _simulateDataLoading() async {
    // 模拟数据加载延迟
    await Future.delayed(Duration(seconds: 2));
    // 切换骨架屏显示状态
    _controller.value = false;
  }
}

在这个示例中:

  1. 我们使用了easy_skeleton提供的SkeletonWidgetSkeletonScreen来创建占位骨架屏。
  2. SkeletonWidget用于创建单个骨架元素,如文本占位符或圆形图片占位符。
  3. SkeletonScreen用于将多个SkeletonWidget组合成一个完整的骨架屏布局。
  4. 通过FutureBuilder模拟了一个异步数据加载过程,并在数据加载完成之前显示骨架屏。
  5. 使用useState钩子来控制骨架屏的显示与隐藏,并通过点击浮动操作按钮来切换显示状态。

希望这个示例能够帮助你理解如何在Flutter项目中使用easy_skeleton插件来实现占位骨架屏效果。

回到顶部