Flutter动画集合插件animated_collection的使用

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

Flutter动画集合插件 animated_collection 的使用

animated_collection 是一个提供简单动画组件和实用方法的Flutter库,用于简化动画的实现。本文将详细介绍如何使用该插件,并提供完整的示例代码。

主要功能

1. AnimatedVisibility

  • 控制Widget的显示与隐藏。
  • 示例:点击按钮切换Widget的可见性。

2. AnimatedBoolean

  • 动态更新布尔值,并触发相应的动画。
  • 示例:通过开关控制文本内容的变化。

3. AnimatedLocation

  • 动态改变Widget的位置。
  • 示例:点击按钮使Widget在不同位置间移动。

4. AnimatedAppearing

  • 动态添加或移除列表项,并带有动画效果。
  • 示例:点击按钮向列表中添加新的颜色块。

5. Animated Flex

  • 包括 AnimatedFlexible, AnimatedExpanded, 和 AnimatedSpacer,用于动态调整布局中的弹性空间。
  • 示例:点击按钮改变弹性空间的比例。

示例代码

以下是完整的示例代码,展示了如何使用上述功能:

import 'dart:math';
import 'package:animated_collection/animated_collection.dart';
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(useMaterial3: true),
      darkTheme: ThemeData.dark(useMaterial3: true),
      home: const DefaultTabController(
        length: 5,
        child: MyHomePage(),
      ),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _visible = true;
  static const _alignments = [
    Alignment.topLeft,
    Alignment.topCenter,
    Alignment.topRight,
    Alignment.centerLeft,
    Alignment.center,
    Alignment.centerRight,
    Alignment.bottomLeft,
    Alignment.bottomCenter,
    Alignment.bottomRight,
  ];

  var _alignment = Alignment.center;
  final _random = Random();
  final _colors = <Color>[];
  bool _boolean = false;
  int _flex = 100;

  @override
  void initState() {
    super.initState();
    _colors.addAll([_generateColor(), _generateColor()]);
  }

  Color _generateColor() {
    return Color(0xff000000 + _random.nextInt(0xffffff));
  }

  void _onPressed() {
    switch (DefaultTabController.of(context).index) {
      case 0:
        setState(() {
          _visible = !_visible;
        });
        break;
      case 1:
        final currentIndex = _alignments.indexOf(_alignment);
        final newIndex = (currentIndex + 1) % _alignments.length;
        setState(() {
          _alignment = _alignments[newIndex];
        });
        break;
      case 2:
        setState(() {
          _colors.addAll([_generateColor(), _generateColor()]);
        });
        break;
      case 3:
        setState(() {
          _boolean = !_boolean;
        });
        break;
      case 4:
        setState(() {
          _flex = _random.nextInt(500);
        });
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('animated_collection'),
        bottom: const TabBar(
          tabs: [
            Tab(text: 'AnimatedVisibility'),
            Tab(text: 'AnimatedLocation'),
            Tab(text: 'AnimatedAppearing'),
            Tab(text: 'AnimatedBoolean'),
            Tab(text: 'AnimatedExpanded'),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _onPressed,
        child: const Icon(Icons.loop),
      ),
      body: TabBarView(
        children: [
          Center(
            child: Container(
              color: Colors.red,
              child: AnimatedVisibility(
                visible: _visible,
                child: ColoredBox(
                  color: Theme.of(context).colorScheme.primaryContainer,
                  child: const SizedBox(
                    height: 200,
                    width: 200,
                    child: Center(
                      child: Text('Hide me'),
                    ),
                  ),
                ),
              ),
            ),
          ),
          AnimatedLocationScope(
            child: Align(
              alignment: _alignment,
              child: AnimatedLocation(
                tag: 'tag',
                child: ColoredBox(
                  color: Theme.of(context).colorScheme.primaryContainer,
                  child: SizedBox.square(
                    dimension: 30 + 5 * _alignments.indexOf(_alignment).toDouble(),
                  ),
                ),
              ),
            ),
          ),
          ListView.builder(
            itemCount: _colors.length,
            itemBuilder: (context, index) {
              return AnimatedAppearing(
                child: ListTile(
                  tileColor: _colors[index],
                ),
              );
            },
          ),
          Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Switch(value: _boolean, onChanged: (_) => _onPressed()),
                AnimatedBoolean(
                  value: _boolean,
                  duration: const Duration(seconds: 5),
                  builder: (context, _, value) {
                    return Text('Value: ${value.toStringAsFixed(2)}');
                  },
                ),
              ],
            ),
          ),
          Center(
            child: Row(
              mainAxisSize: MainAxisSize.max,
              children: [
                Expanded(
                  flex: 100,
                  child: ColoredBox(
                    color: Theme.of(context).colorScheme.primaryContainer,
                    child: const Center(
                      child: Text(
                        'Expanded 100',
                        textAlign: TextAlign.center,
                      ),
                    ),
                  ),
                ),
                AnimatedExpanded(
                  flex: _flex,
                  child: ColoredBox(
                    color: Theme.of(context).colorScheme.secondaryContainer,
                    child: Center(
                      child: Text(
                        'Expanded $_flex',
                        textAlign: TextAlign.center,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

总结

通过使用 animated_collection 插件,您可以轻松地为您的Flutter应用添加各种动画效果。希望这个示例能够帮助您更好地理解和使用该插件。


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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用animated_collection插件的示例代码。animated_collection插件提供了一种简单的方式来为集合中的项目添加动画效果。

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

dependencies:
  flutter:
    sdk: flutter
  animated_collection: ^2.0.0 # 请检查最新版本号

然后运行flutter pub get来获取依赖。

接下来是一个简单的示例,展示如何使用AnimatedListAnimatedListState结合animated_collection插件来创建一个带有动画效果的列表:

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

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

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

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

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  final List<String> _items = List<String>.generate(10, (i) => "Item $i");
  AnimatedListController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimatedListController(
      vsync: this,
      initialItemCount: _items.length,
    )..addItem(); // Initial call to setup the listener
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _addItem() {
    setState(() {
      _items.add("Item ${_items.length}");
    });
    _controller.addItem();
  }

  void _removeItemAt(int index) {
    setState(() {
      _items.removeAt(index);
    });
    _controller.removeItem(index, (context, animation) {
      return SlideTransition(
        position: Tween<Offset>(
          begin: Offset.zero,
          end: const Offset(-1, 0),
        ).animate(animation),
        child: Dismissible(
          key: ValueKey(_items[index]),
          child: ListTile(
            title: Text(_items[index]),
          ),
          onDismissed: (direction) {
            // This is called after the item is removed from the list
          },
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Animated Collection Demo'),
      ),
      body: AnimatedList(
        controller: _controller,
        itemBuilder: (context, index, animation) {
          return SlideTransition(
            position: Tween<Offset>(
              begin: const Offset(1, 0),
              end: Offset.zero,
            ).animate(animation),
            child: ListTile(
              leading: IconButton(
                icon: Icon(Icons.delete),
                onPressed: () => _removeItemAt(index),
              ),
              title: Text(_items[index]),
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addItem,
        tooltip: 'Add Item',
        child: Icon(Icons.add),
      ),
    );
  }
}

代码解释:

  1. 依赖导入:在pubspec.yaml文件中添加animated_collection依赖。
  2. 创建应用MyApp是应用的根widget,包含一个MaterialApp
  3. 主页面MyHomePage是一个StatefulWidget,包含一个带有动画效果的列表。
  4. 动画控制器:使用AnimatedListController来控制动画列表。在initState中初始化控制器,并在dispose中释放它。
  5. 添加和移除项目
    • _addItem方法向列表中添加一个新项目,并通知AnimatedListController添加一个新的动画。
    • _removeItemAt方法从列表中移除指定索引的项目,并使用AnimatedListControllerremoveItem方法来处理移除动画。
  6. 构建动画列表:使用AnimatedList来构建列表,itemBuilder回调为每个项目创建一个带有滑动动画效果的ListTile
  7. 浮动操作按钮FloatingActionButton用于添加新项目。

这个示例展示了如何使用animated_collection插件结合AnimatedListAnimatedListController来创建带有添加和移除动画效果的列表。希望这对你有所帮助!

回到顶部