按下按钮时开始播放动画-颤振

时间:2020-01-29 12:10:34

标签: 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小部件(使用Container代表卡片和卡片组):

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),
              ),
      ),
    );
  }
}

谢谢!

1 个答案:

答案 0 :(得分:2)

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

代码段

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

工作演示

enter image description here

完整代码

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),
              ),
      ),
    );
  }
}