Flutter动画效果插件shimmer_fade的使用

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

Flutter动画效果插件shimmer_fade的使用

shimmer_fade 插件提供了在你的应用中添加类似Facebook或Netflix上的闪动效果的一种简单方式。它快速、轻量且易于设置。

Shimmer Fade 示例

如何使用

首先,在你的Dart文件中导入该包:

import 'package:shimmer_fade/shimmer_fade.dart';

1. 设置Shimmer Fade容器

ShimmerFadeContainer 是必需的,用于同步所有子项的闪动动画。以下是设置方法:

ShimmerFadeContainer(
  fromColor: const Color(0x11F4F4F4),   // 从颜色
  toColor: const Color(0x33F4F4F4),     // 到颜色
  duration: const Duration(seconds: 3), // 动画持续时间
  child: ListView(
    physics: const NeverScrollableScrollPhysics(), // 禁止滚动
    children: [
      const SizedBox(height: 16), // 间距
      _buildTopRowList(),
      const SizedBox(height: 16), // 间距
      _buildListItem(),
      _buildListItem(),
      _buildListItem(),
    ],
  ),
)

2. 应用闪动效果

ShimmerFadeContainer 中,你可以通过将加载小部件包裹在 ShimmerFade 小部件中来应用闪动效果。这将保留子部件的形状并应用闪动效果。闪动动画的颜色将与 ShimmerFadeContainer 保持一致。

ShimmerFade(
  child: CardListItem(),
)

示例代码

以下是一个完整的示例代码:

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

class MyShimmerScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: ShimmerFadeContainer(
        fromColor: const Color(0x11F4F4F4),
        toColor: const Color(0x33F4F4F4),
        duration: const Duration(seconds: 3),
        child: ListView(
          physics: const NeverScrollableScrollPhysics(),
          children: [
            const SizedBox(height: 16),
            _buildTopRowList(),
            const SizedBox(height: 16),
            ShimmerFade(
              child: _buildListItem(),
            ),
            ShimmerFade(
              child: _buildListItem(),
            ),
            ShimmerFade(
              child: _buildListItem(),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildTopRowList() {
    // 你的小部件代码
  }

  Widget _buildListItem() {
    // 你的小部件代码
  }
}

完整示例

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

void main() {
  runApp(
    const MaterialApp(
      home: ExampleUiLoadingAnimation(),
      debugShowCheckedModeBanner: false,
    ),
  );
}

class ExampleUiLoadingAnimation extends StatefulWidget {
  const ExampleUiLoadingAnimation({
    super.key,
  });

  [@override](/user/override)
  State<ExampleUiLoadingAnimation> createState() => _ExampleUiLoadingAnimationState();
}

class _ExampleUiLoadingAnimationState extends State<ExampleUiLoadingAnimation> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: ShimmerFadeContainer(
        fromColor: const Color(0x11F4F4F4),
        toColor: const Color(0x33F4F4F4),
        duration: const Duration(seconds: 3),
        child: ListView(
          physics: const NeverScrollableScrollPhysics(),
          children: [
            const SizedBox(height: 16),
            _buildTopRowList(),
            const SizedBox(height: 16),
            _buildListItem(),
            _buildListItem(),
            _buildListItem(),
          ],
        ),
      ),
    );
  }

  Widget _buildTopRowList() {
    return SizedBox(
      height: 72,
      child: ListView(
        physics: const NeverScrollableScrollPhysics(),
        scrollDirection: Axis.horizontal,
        shrinkWrap: true,
        children: [
          const SizedBox(width: 16),
          _buildTopRowItem(),
          _buildTopRowItem(),
          _buildTopRowItem(),
          _buildTopRowItem(),
          _buildTopRowItem(),
          _buildTopRowItem(),
        ],
      ),
    );
  }

  Widget _buildTopRowItem() {
    return const CircleListItem();
  }

  Widget _buildListItem() {
    return const ShimmerFade(
      child: CardListItem(),
    );
  }
}

//----------- 列表项 ---------
class CircleListItem extends StatelessWidget {
  const CircleListItem({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
      child: Container(
        width: 54,
        height: 54,
        decoration: const BoxDecoration(
          color: Colors.black,
          shape: BoxShape.circle,
        ),
        child: ClipOval(
          child: Image.network(
            'https://docs.flutter.dev/cookbook'
            '/img-files/effects/split-check/Avatar1.jpg',
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }
}

class CardListItem extends StatelessWidget {
  const CardListItem({
    super.key,
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _buildImage(),
          const SizedBox(height: 16),
          _buildText(),
        ],
      ),
    );
  }

  Widget _buildImage() {
    return AspectRatio(
      aspectRatio: 16 / 9,
      child: Container(
        width: double.infinity,
        decoration: BoxDecoration(
          color: Colors.black,
          borderRadius: BorderRadius.circular(16),
        ),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(16),
          child: Image.network(
            'https://docs.flutter.dev/cookbook/img-files/effects/split-check/Food1.jpg',
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }

  Widget _buildText() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          width: double.infinity,
          height: 24,
          decoration: BoxDecoration(
            color: Colors.black,
            borderRadius: BorderRadius.circular(16),
          ),
        ),
        const SizedBox(height: 16),
        Container(
          width: 250,
          height: 24,
          decoration: BoxDecoration(
            color: Colors.black,
            borderRadius: BorderRadius.circular(16),
          ),
        ),
      ],
    );
  }
}

更多关于Flutter动画效果插件shimmer_fade的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter动画效果插件shimmer_fade的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


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

首先,确保你已经在pubspec.yaml文件中添加了shimmer_fade依赖:

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

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

接下来,在你的Flutter项目中,你可以按照以下方式使用ShimmerFade组件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Shimmer Fade 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();
    // 模拟数据加载
    Future.delayed(Duration(seconds: 2), () {
      setState(() {
        isLoading = false;
        data = List.generate(10, (index) => 'Item $index');
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Shimmer Fade Demo'),
      ),
      body: isLoading
          ? ShimmerFade(
              child: ListView.builder(
                itemCount: 10,
                itemBuilder: (context, index) {
                  return Padding(
                    padding: const EdgeInsets.symmetric(vertical: 8.0),
                    child: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(8),
                        color: Colors.grey[200]!,
                      ),
                      height: 50,
                      alignment: Alignment.center,
                      child: Text(
                        '', // 在加载时显示空字符串
                        style: TextStyle(color: Colors.black),
                      ),
                    ),
                  );
                },
              ),
            )
          : ListView.builder(
              itemCount: data.length,
              itemBuilder: (context, index) {
                return Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: Container(
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(8),
                      color: Colors.grey[200]!,
                    ),
                    height: 50,
                    alignment: Alignment.center,
                    child: Text(
                      data[index],
                      style: TextStyle(color: Colors.black),
                    ),
                  ),
                );
              },
            ),
    );
  }
}

在这个示例中:

  1. MyHomePage是一个有状态组件,它模拟了一个数据加载过程。
  2. 当数据正在加载时(isLoading == true),ShimmerFade组件被用来显示一个带有动画效果的占位符列表。
  3. 占位符列表中的每个项都是一个带有灰色背景和圆角边框的容器。
  4. 当数据加载完成后(isLoading == false),显示实际的数据列表。

ShimmerFade组件会自动处理动画效果,你只需将需要显示动画效果的子组件作为它的子组件即可。

回到顶部