Flutter自定义动画图标

daupos2t  于 2022-11-30  发布在  Flutter
关注(0)|答案(5)|浏览(270)

我正在寻找一个项目,得到添加和从列表中删除。
我正在寻找的是有+图标和-图标和动画之间的2为一个干净和顺利的外观。
我有下面的代码

Container(
            padding: EdgeInsets.fromLTRB(0, 0, 20, 0),
            child: AnimatedIcon(
              icon: AnimatedIcons.home_menu,
              progress: _animationController,
              color: Colors.white,
            ))

void _handleOnPressed() {
setState(() {
  isPlaying = !isPlaying;
  isPlaying
      ? _animationController.forward()
      : _animationController.reverse();
  });
}

这对于精细的内置动画图标在Flutter。
我希望使用+和-图标,但外观相同。
有办法做到这一点吗?

8i9zcol2

8i9zcol21#

我知道它不像AnimatedIcon那么漂亮,但你实际上可以得到非常相似的过渡与任何2个图标的选择,只需几行代码:

IconButton(
      icon: AnimatedSwitcher(
          duration: const Duration(milliseconds: 300),
          transitionBuilder: (child, anim) => RotationTransition(
                turns: child.key == ValueKey('icon1')
                    ? Tween<double>(begin: 1, end: 0.75).animate(anim)
                    : Tween<double>(begin: 0.75, end: 1).animate(anim),
                child: FadeTransition(opacity: anim, child: child),
              ),
          child: _currIndex == 0
              ? Icon(Icons.close, key: const ValueKey('icon1'))
              : Icon(
                  Icons.arrow_back,
                  key: const ValueKey('icon2'),
                )),
      onPressed: () {
        setState(() {
          _currIndex = _currIndex == 0 ? 1 : 0;
        });
      },
    );

结果:

或者,您可以使用ScaleTransition而不是FadeTransition,并获得更相似的动画:

IconButton(
      icon: AnimatedSwitcher(
          duration: const Duration(milliseconds: 350),
          transitionBuilder: (child, anim) => RotationTransition(
                turns: child.key == ValueKey('icon1')
                    ? Tween<double>(begin: 1, end: 0.75).animate(anim)
                    : Tween<double>(begin: 0.75, end: 1).animate(anim),
                child: ScaleTransition(scale: anim, child: child),
              ),
          child: _currIndex == 0
              ? Icon(Icons.close, key: const ValueKey('icon1'))
              : Icon(
                  Icons.arrow_back,
                  key: const ValueKey('icon2'),
                )),
      onPressed: () {
        setState(() {
          _currIndex = _currIndex == 0 ? 1 : 0;
        });
      },
    )

结果:

通过这种方法,您可以使用任何想要的图标,并且不需要创建单独的AnimationController来控制过渡,这与AnimatedIcon不同

idv4meu8

idv4meu82#

你很幸运,我的朋友!Flutter已经用AnimatedIcon()覆盖了你
AnimatedIcon Class in the docs
Animated Icon Widget of the week Video
现在用Flare来动画你的图标。Jeff Delaney为此做了一个很好的教程。
https://fireship.io/lessons/animated-navigation-flutter-flare/

ergxz8rk

ergxz8rk3#

Flutter提供了AnimatedIcon可以使用,这是一个如何使用它的例子。

class _CreatePackageViewState extends State<CreatePackageView>
    with SingleTickerProviderStateMixin {  
       bool expanded = true;
       late AnimationController controller;
      @override
       void initState() {
        super.initState();
        controller = AnimationController(
          vsync: this,
          duration: Duration(milliseconds: 400),
          reverseDuration: Duration(milliseconds: 400),
        );
      }


      IconButton(
            icon: AnimatedIcon(
              icon: AnimatedIcons.menu_close,
              progress: controller,
              semanticLabel: 'Show menu',
            ),
            onPressed: () {
              setState(() {
                expanded ? controller.forward() : controller.reverse();
                expanded = !expanded;
              });
            }),

    }
rslzwgfq

rslzwgfq4#

Flutter团队似乎使用了一个名为vitool的命令行工具来将SVG转换为可以作为动画图标使用的路径。如果您有一个相对简单的动画SVG,您可以尝试运行此存储库的bin文件夹中的main.dart命令行工具:https://github.com/flutter/flutter/tree/master/dev/tools/vitool。我还没有尝试,但是如果发现任何问题,我会尝试并报告。输出应该如下所示:

const _AnimatedIconData _$menu_arrow = _AnimatedIconData(
  Size(48.0, 48.0),
  <_PathFrames>[
    _PathFrames(
      opacities: <double>[
        1.0,
        1.0,
        1.0,
        1.0,
        1.0,
        1.0,
        1.0,
(...)
eivnm1vs

eivnm1vs5#

自定义动画需要3样东西
1.动画控制器
1.吐温
1.动画效果
简单示例如下

import 'package:flutter/material.dart';

class AnimationsPractice extends StatefulWidget {
  @override
  _AnimationsPracticeState createState() => _AnimationsPracticeState();
}

class _AnimationsPracticeState extends State<AnimationsPractice> with SingleTickerProviderStateMixin {

  AnimationController controller;
  Animation animation;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
        duration: Duration(milliseconds: 500),
        vsync: this);

   animation = ColorTween(begin: Colors.purple, end: Colors.red[700]).animate(controller);

    controller.forward();

    animation.addStatusListener((status) {
      if(status == AnimationStatus.completed){
        controller.reverse(from: 1.0);
        print(animation.value);
      }
      else if(status == AnimationStatus.dismissed){
        controller.forward();
      }
    });

    controller.addListener(() {
      setState(() {
      });
      print(controller.value);
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.yellow,
      appBar: AppBar(
        title: Text('Heart Beat'),
      ),
      body: Center(
        child: Icon(
          Icons.favorite,
          size: animation.value * 100,
        ),
      ),
    );
  }
}

相关问题