【问题标题】:Starting An Animation When A Button Is Pressed - Flutter按下按钮时启动动画 - Flutter
【发布时间】:2020-05-14 22:26:35
【问题描述】:

我是 Flutter 的新手,我正在尝试创建一个 UI,其中包含卡片组和显示的卡片。每当用户按下卡片组时,我都希望显示一张新卡片(使用定位小部件的翻转和移动动画)。

问题是,我不明白如何让动画在每次创建小部件时出现。

我试图让动画进入我创建的小部件的初始化状态,但这似乎不起作用。

这是应用小部件树:

class _DeckState extends State<Deck> with TickerProviderStateMixin {
  List<MyCard> _cards= <MyCard>[];

  @override
  void initState() {
    super.initState();
    _cards.insert(0, MyCard());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("NLP Deck"),
      ),
      body: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          Container(),
          _cards[0],
          Positioned(
            top: 40.0,
            child: GestureDetector(
              onTap: PressedDeck,
              child: Container(
                width: 100.0,
                height: 128.0,
                decoration: BoxDecoration(color: Colors.brown),
              ),
            ),
          ),
        ],
      ),
    );
  }

  void PressedDeck() {
    setState(() {
      _cards.insert(0, new MyCard());
    });
  }
}

这是我创建的 Card 小部件(使用 Containers 来表示卡片和卡片组):

class _CardState extends State<MyCard> with TickerProviderStateMixin {
  AnimationController animController;
  Animation flipAnimation;
  Animation positionAnimation;

  @override
  void initState() {
    super.initState();
    animController = new AnimationController(
        vsync: this, duration: Duration(milliseconds: 1000));
    flipAnimation = Tween<double>(begin: 1.0, end: 0).animate(animController);
    positionAnimation =
        Tween<double>(begin: 40.0, end: 240.0).animate(animController);

    animController.forward();
  }

  @override
  Widget build(BuildContext context) {
    return PositionTransition(
      position: positionAnimation,
      flip: flipAnimation,
    );
  }

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

class PositionTransition extends AnimatedWidget {
  PositionTransition({
    @required Animation<double> position,
    @required this.flip,
  }) : super(listenable: position);

  final Animation<double> flip;

  @override
  Widget build(BuildContext context) {
    final position = super.listenable as Animation<double>;
    return Positioned(
      top: position.value,
      child: Transform(
        alignment: FractionalOffset.center,
        transform: Matrix4.rotationX(math.pi * flip.value),
        child: flip.value >= 0.5
            ? Container(
                width: 100,
                height: 128,
                decoration: BoxDecoration(color: Colors.deepOrange),
              )
            : Container(
                width: 100,
                height: 128,
                decoration: BoxDecoration(color: Colors.amber),
              ),
      ),
    );
  }
}

谢谢!

【问题讨论】:

    标签: flutter


    【解决方案1】:

    您可以在下面复制粘贴运行完整代码
    您可以在didUpdateWidget 中致电animController.reset()forward()
    出于演示目的,我将动画持续时间更改为 3 秒
    具体可以参考https://medium.com/sk-geek/flutter-experiment-to-trigger-animation-when-parent-setstate-84e949530b64

    代码sn-p

    @override
      void didUpdateWidget(MyCard oldWidget) {
        animController.reset();
        animController.forward();
        super.didUpdateWidget(oldWidget);
      }
    

    工作演示

    完整代码

    import 'package:flutter/material.dart';
    import 'dart:math' as math;
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Deck(),
        );
      }
    }
    
    class Deck extends StatefulWidget {
      @override
      _DeckState createState() => _DeckState();
    }
    
    class _DeckState extends State<Deck> with TickerProviderStateMixin {
      List<MyCard> _cards = <MyCard>[];
    
      @override
      void initState() {
        super.initState();
        _cards.insert(0, MyCard());
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("NLP Deck"),
          ),
          body: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Container(),
              _cards[0],
              Positioned(
                top: 40.0,
                child: GestureDetector(
                  onTap: PressedDeck,
                  child: Container(
                    width: 100.0,
                    height: 128.0,
                    decoration: BoxDecoration(color: Colors.brown),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    
      void PressedDeck() {
        print("PressedDeck");
        setState(() {
          _cards.insert(0, new MyCard());
        });
        print("cards length ${_cards.length}");
      }
    }
    
    class MyCard extends StatefulWidget {
      @override
      _MyCardState createState() => _MyCardState();
    }
    
    class _MyCardState extends State<MyCard> with TickerProviderStateMixin {
      AnimationController animController;
      Animation flipAnimation;
      Animation positionAnimation;
    
      @override
      void initState() {
        print("My card init State");
        super.initState();
        animController =
            new AnimationController(vsync: this, duration: Duration(seconds: 3));
        flipAnimation = Tween<double>(begin: 1.0, end: 0).animate(animController);
        positionAnimation =
            Tween<double>(begin: 40.0, end: 240.0).animate(animController);
    
        animController.forward();
      }
    
      @override
      void didUpdateWidget(MyCard oldWidget) {
        animController.reset();
        animController.forward();
        super.didUpdateWidget(oldWidget);
      }
    
      @override
      Widget build(BuildContext context) {
        return PositionTransition(
          position: positionAnimation,
          flip: flipAnimation,
        );
      }
    
      @override
      void dispose() {
        animController.dispose();
        super.dispose();
      }
    }
    
    class PositionTransition extends AnimatedWidget {
      PositionTransition({
        @required Animation<double> position,
        @required this.flip,
      }) : super(listenable: position);
    
      final Animation<double> flip;
    
      @override
      Widget build(BuildContext context) {
        final position = super.listenable as Animation<double>;
        return Positioned(
          top: position.value,
          child: Transform(
            alignment: FractionalOffset.center,
            transform: Matrix4.rotationX(math.pi * flip.value),
            child: flip.value >= 0.5
                ? Container(
                    width: 100,
                    height: 128,
                    decoration: BoxDecoration(color: Colors.deepOrange),
                  )
                : Container(
                    width: 100,
                    height: 128,
                    decoration: BoxDecoration(color: Colors.amber),
                  ),
          ),
        );
      }
    }
    

    【讨论】:

    • 非常感谢,非常有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    • 1970-01-01
    相关资源
    最近更新 更多