【问题标题】:Rotate icon 180 degree with animation in flutter在颤动中旋转图标 180 度动画
【发布时间】:2021-09-11 11:26:00
【问题描述】:

我有一个IconButton,通常,它的图标是Icons.expand_more,但是当我按下它时,它的图标应该是Icons.expand_less。我想对此进行动画处理,以便如果我按下该按钮,它将旋转并从 upwords 指向 downwords。同样,当我按下expand_less 时,它应该变成expand_more 并带有旋转动画。我怎样才能做到这一点? 以下是我的代码:

    IconButton(
      icon:  _expanded ? Icon(Icons.expand_less) : Icon(Icons.expand_more),
      onPressed: () {
        setState(() {
           _expanded = !_expanded;
        });
      },
   )

我尝试使用 animatedContainer 但它不起作用,因为我使用了两个不同的图标,并且我无法实现旋转效果。 我也尝试使用以下方法旋转图标,但是当它从 0 度旋转到 180 度时无法显示动画。

IconButton(
              icon: AnimatedContainer(
                  duration: Duration(seconds: 3),
                  child: Transform.rotate(
                      angle: _expanded ? 0 : 180 * math.pi / 180,
                      child: Icon(Icons.expand_less))),
              // icon:
              //     _expanded ? Icon(Icons.expand_less) : Icon(Icons.expand_more),
              onPressed: () {
                setState(() {
                  _expanded = !_expanded;
                });
              },
            )

这是展开前的:

这是扩展后的:

我想要按钮点击时的旋转动画。

【问题讨论】:

  • 感谢大家的回答!我发布了完整的解决方案below

标签: flutter dart iconbutton


【解决方案1】:

感谢@krumpli。

  1. 定义AnimationController _controller

  2. 定义init方法为:

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 300),
      upperBound: 0.5,
    );
  }
  1. 定义dispose方法为:
@override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
  1. 使用小部件RotationTransition
RotationTransition(
              turns: Tween(begin: 0.0, end: 1.0).animate(_controller),
              child: IconButton(
                icon: Icon(Icons.expand_less),
                onPressed: () {
                  setState(() {
                    if (_expanded) {
                      _controller..reverse(from: 0.5);
                    } else {
                      _controller..forward(from: 0.0);
                    }
                    _expanded = !_expanded;
                  });
                },
              ),
            )

别忘了在类定义中添加with SingleTickerProviderStateMixin

【讨论】:

    【解决方案2】:

    试试这个: 添加动画控制器:AnimationController _animationController:

    initState() {
        _animationController = new AnimationController(
            vsync: this, duration: Duration(milliseconds: 300));
        }
    

    将您的图标包装在此:

    RotationTransition(
             turns: Tween(begin: 0.0, end: 1.0)
                    .animate(_animationController),
             child: IconButton(icon: //YOUR ICON),
             onPressed: () {
                 setState(() {
            _animationController1.forward(from: 0.0);
          });
         },
       ),
     )
    

    最后:

      @override
      void dispose() {
        super.dispose();
        _animationController?.dispose();
      }
    

    【讨论】:

    • 谢谢老兄!您的解决方案完成了旋转动画的工作,但我需要在展开和折叠时使用特定的旋转动画,不过我从您的解决方案中发现了这一点。
    • 是的,使用标志进行简单修复。乐于助人!
    【解决方案3】:

    看看这个test sample我为你准备的东西。

    这也应用了一条曲线,这是一个很好的 Flutter 建议。

    import 'package:flutter/material.dart';
    
    class RotateIcon extends StatefulWidget {
      const RotateIcon({Key? key}) : super(key: key);
    
      @override
      _RotateIconState createState() => _RotateIconState();
    }
    
    class _RotateIconState extends State<RotateIcon>
        with SingleTickerProviderStateMixin {
      late final AnimationController _controller;
      late final Animation<double> _animation;
    
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(
            duration: const Duration(milliseconds: 500), vsync: this);
        _animation =
            Tween(begin: 0.0, end: .5).animate(CurvedAnimation(
            parent: _controller, curve: Curves.easeOut));
        }
    
      @override
      void dispose() {
        super.dispose();
        _controller.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
              child: Column(
                children: [
                  RotationTransition(
                    turns: _animation,
                    child: const Icon(Icons.expand_more),
                  ),
                  ElevatedButton(
                      onPressed: () {
                        if (_controller.isDismissed) {
                          _controller.forward();
                        } else {
                          _controller.reverse();
                        }
                      },
                      child: const Text("Animate"))
                ],
              )),
        );
      }
    }
    
    

    【讨论】:

    • 非常感谢!这正是我想要的:)
    • 好的,我很高兴我的回答足够好。您现在可以使用您的代码自定义它并更改动画的时间
    • 我从@krumpli 的回答中找到了解决方案,但是在看了你的解决方案之后(?)我确认了!
    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    • 好的,我已经更新了答案,添加了整个类的重要代码。这样更好吗?
    最近更新 更多