Flutter动画堆叠插件animated_stack_widget的使用

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

Flutter动画堆叠插件animated_stack_widget的使用

animated_stack_widget简介

animated_stack_widget插件让开发者能够以类似AnimatedList为列表添加动画的方式,轻松地为Stack中的子组件添加和移除动画效果。它简化了在Flutter中实现动态、交互式用户界面的过程。

开始使用

要开始使用animated_stack_widget,你可以参考官方提供的示例应用,该应用展示了如何创建一个带有动画效果的Stack布局,以及如何通过手势或按钮操作来动态地向Stack中添加或移除子组件。下面是一个完整的示例demo:

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

// 假设SlidingItem, FadingItem和ItemData是自定义组件和数据模型,用于展示和管理动画项。
import 'sliding_item.dart';
import 'fading_item.dart';
import 'item_data.dart';

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

class AnimatedStackExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'AnimatedStack Demo',
      home: AnimatedStackExampleHomePage(title: 'AnimatedStack Demo'),
    );
  }
}

class AnimatedStackExampleHomePage extends StatefulWidget {
  AnimatedStackExampleHomePage({Key? key, required this.title})
      : super(key: key);

  final String title;

  @override
  _AnimatedStackExampleHomePageState createState() =>
      _AnimatedStackExampleHomePageState();
}

class _AnimatedStackExampleHomePageState
    extends State<AnimatedStackExampleHomePage> {
  final GlobalKey<AnimatedStackState> _animatedStackKey =
      GlobalKey<AnimatedStackState>();
  late AnimatedStackManager<ItemData> _animatedStackManager;

  @override
  void initState() {
    super.initState();
    _animatedStackManager = AnimatedStackManager<ItemData>(
      animatedStackKey: _animatedStackKey,
      removedItemBuilder: _buildRemovedItem,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.delete_sweep),
        onPressed: () => _animatedStackManager.clear(),
      ),
      body: Center(
        child: GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTapUp: (tapDetails) {
            _insert(tapDetails.localPosition.dx, tapDetails.localPosition.dy);
          },
          child: Column(children: [
            Expanded(
              child: Container(
                child: LayoutBuilder(
                  builder: (context, constraints) => AnimatedStack(
                    key: _animatedStackKey,
                    initialItemCount: 0,
                    itemBuilder: (context, index, animation) =>
                        _buildItem(context, index, animation, constraints),
                  ),
                ),
              ),
            ),
            Padding(
              padding: EdgeInsets.all(8),
              child: TextButton(
                onPressed: () {
                  final halfWidth = MediaQuery.of(context).size.width / 2;
                  _animatedStackManager
                      .removeWhere((itemData) => itemData.x < halfWidth);
                },
                child: Text('Remove popups with\n left edge in left half'),
                style: ButtonStyle(
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  backgroundColor: MaterialStateProperty.all(Colors.blue),
                ),
              ),
            ),
          ]),
        ),
      ),
    );
  }

  Widget _buildItem(BuildContext context, int index,
      Animation<double> animation, BoxConstraints constraints) {
    return SlidingItem(
      itemData: _animatedStackManager[index],
      animation: animation,
      onTap: () => _remove(_animatedStackManager[index]),
      constraints: constraints,
    );
  }

  Widget _buildRemovedItem(
      ItemData itemData, BuildContext context, Animation<double> animation) {
    return FadingItem(
      itemData: itemData,
      animation: animation,
    );
  }

  void _insert(double x, double y) {
    _animatedStackManager.insert(
        _animatedStackManager.length, ItemData(x: x, y: y));
  }

  void _remove(ItemData item) {
    final index = _animatedStackManager.indexOf(item);
    _animatedStackManager.removeAt(index);
  }
}

在这个例子中,我们创建了一个简单的Flutter应用程序,它使用animated_stack_widget库来构建一个可以响应点击事件,并且能够根据位置动态插入新元素到Stack中,同时支持移除特定条件下的元素(例如,位于屏幕左侧的元素)。此外,还提供了一个浮动按钮用于清空所有元素。

注意事项

  • SlidingItemFadingItem 是为了演示目的而假设存在的组件,你需要根据实际需求自行实现这些组件。
  • ItemData 类用于存储每个项目的数据,如位置信息等,同样需要根据实际情况定义。
  • 请确保已经安装了animated_stack_widget插件,可以通过在pubspec.yaml文件中添加依赖来完成安装。

致谢

AnimatedStack小部件是对Flutter内置AnimatedList小部件的一种改编,因此对于原始AnimatedList小部件的设计者表示感谢。


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

1 回复

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


当然,以下是一个关于如何在Flutter中使用animated_stack_widget插件的示例代码。这个插件允许你创建带有动画效果的堆叠小部件。首先,你需要确保你的项目中已经包含了animated_stack_widget。你可以通过在你的pubspec.yaml文件中添加以下依赖项来实现:

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

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

以下是一个完整的示例代码,展示了如何使用animated_stack_widget来创建一个带有动画效果的堆叠小部件:

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

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

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

class AnimatedStackWidgetDemo extends StatefulWidget {
  @override
  _AnimatedStackWidgetDemoState createState() => _AnimatedStackWidgetDemoState();
}

class _AnimatedStackWidgetDemoState extends State<AnimatedStackWidgetDemo> with SingleTickerProviderStateMixin {
  bool isFirstCardVisible = true;
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 1),
      vsync: this,
    )..repeat(reverse: true);
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Animated Stack Widget Demo'),
      ),
      body: Center(
        child: AnimatedStack(
          alignment: Alignment.center,
          spacing: 10.0,
          children: [
            AnimatedStackItem(
              child: Card(
                color: Colors.blue,
                child: Center(
                  child: Text(
                    'First Card',
                    style: TextStyle(color: Colors.white, fontSize: 24),
                  ),
                ),
              ),
              visible: isFirstCardVisible,
              animation: Tween<double>(begin: 1.0, end: 0.0).animate(_controller),
              alignment: Alignment.center,
            ),
            AnimatedStackItem(
              child: Card(
                color: Colors.red,
                child: Center(
                  child: Text(
                    'Second Card',
                    style: TextStyle(color: Colors.white, fontSize: 24),
                  ),
                ),
              ),
              visible: !isFirstCardVisible,
              animation: Tween<double>(begin: 0.0, end: 1.0).animate(_controller),
              alignment: Alignment.center,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            isFirstCardVisible = !isFirstCardVisible;
          });
        },
        tooltip: 'Toggle Cards',
        child: Icon(Icons.swap_horiz),
      ),
    );
  }
}

在这个示例中,我们创建了一个包含两个堆叠卡片的AnimatedStack。通过使用AnimatedStackItem,我们可以为每个卡片指定一个动画和可见性状态。_controller控制动画的播放,当用户点击浮动操作按钮时,通过调用setState来切换卡片的可见性,并触发动画。

请注意,animated_stack_widget插件的具体API和用法可能会随着版本的更新而变化,因此请参考插件的官方文档以获取最新的使用方法和示例。

回到顶部