【问题标题】:Flip animation with flutter_redux使用 flutter_redux 翻转动画
【发布时间】:2018-04-10 01:58:02
【问题描述】:

我有一个时间显示应用程序,每次时间更改时都会更改时间。我真的很想知道如何为数字添加“文本翻转”动画。当应用程序启动时,数字立即翻转到位,但每次发生变化时都无法翻转。这是我的代码:

/// Flutter Packages
import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';


class ListTimeWidget extends StatefulWidget { ... }


class _ListTimeWidgetState extends State<ListTimeWidget> with SingleTickerProviderStateMixin {

  Animation<double> _animation;
  AnimationController _controller;

  /// Methods
  String _selectCorrectTime(Store<DateTime> store) {
    Map<String, int> timeDelta = {
      'years': store.state.year,
      'months': store.state.month,
      'days': store.state.day,
      'hours': store.state.hour,
      'minutes': store.state.minute,
    };

    if (timeDelta.containsKey(widget.timeUnit))
      return timeDelta[widget.timeUnit].toString().padLeft(2, '0');
    else
      return '##';
  }

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

    this._controller = new AnimationController(
      vsync: this,
      duration: const Duration(seconds: 1),
    );

    this._animation = new Tween(
        begin: 0.0,
        end: 1.0,
    ).animate(this._controller);

  }

  @override
  Widget build(BuildContext context) {
    return new AnimatedBuilder(
        animation: this._animation,

        builder: (BuildContext context, Widget child) {
          final Matrix4 transform = new Matrix4.identity()
            ..scale(1.0, this._animation.value, 1.0);

          return new Transform(
            transform: transform,
            alignment: FractionalOffset.center,
            child: child,
          );
        },

        child: new StoreConnector<DateTime, String>(
          converter: (store) => this._selectCorrectTime(store),
          builder: (context, time) {
            this._controller.forward();
            return new Text(
              time,
              textAlign: TextAlign.left,
              style: new TextStyle(fontSize: 100.0),
            );
            },
        )

    );
  }

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

我得到的结果是一开始的动画,当数字从屏幕外重新出现时,而不是在时间改变时:

我是 Flutter 动画的新手,任何建议都会有所帮助。

【问题讨论】:

  • 您是否尝试在您的状态上设置一个 bool 属性,当新状态发生时变为 true?
  • 当一个新状态发生时,构建器被调用(我添加了一些 print() 语句并看到了一些结果)

标签: animation flutter


【解决方案1】:

我已经想出了如何结合flutter_redux来完成一个定时动画。通过将StoreConnector 拆分为它自己的Stateless Widget,以及它自己的Stateful Widget 中的动画,forward 方法不再引发问题。

这是我的示例代码:

/// Flutter Packages
import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';

/// Dart Packages
import 'dart:async';

class ListTimeWidget extends StatelessWidget {
  /// Attributes
  final String timeUnit;

  /// Constructors
  const ListTimeWidget({
    this.timeUnit,
  });

  /// Methods
  String _selectCorrectTime(Store<DateTime> store) {
    Map<String, int> timeDelta = {
      'years': store.state.year,
      'months': store.state.month,
      'days': store.state.day,
      'hours': store.state.hour,
      'minutes': store.state.minute,
    };

    if (timeDelta.containsKey(this.timeUnit))
      return timeDelta[this.timeUnit].toString().padLeft(2, '0');
    else
      return '##';
  }

  @override
  Widget build(BuildContext context) =>
      new StoreConnector<DateTime, String>(
          converter: (store) => this._selectCorrectTime(store),
          builder: (context, time) => new ListTimeWidgetAnimation(amountOfTime: time),
      );
}

class ListTimeWidgetAnimation extends StatefulWidget { ... }


class _ListTimeWidgetAnimationState extends State<ListTimeWidgetAnimation> with SingleTickerProviderStateMixin {

  /// Attributes
  Animation<double> _animation;
  AnimationController _controller;
  String _currentTime;

  /// Methods
  Future<Null> _changeTimeAnimation() async {
    await this._controller.reverse();

    setState(() {
      this._currentTime = widget.amountOfTime;
    });

    await this._controller.forward();
  }

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

    this._controller = new AnimationController(
      vsync: this,
      duration: const Duration(seconds: 1),
    );

    this._animation = new Tween(
        begin: 0.0,
        end: 1.0,
    ).animate(this._controller);

    this._currentTime = widget.amountOfTime;
    this._controller.forward();
  }

  @override
  Widget build(BuildContext context) {

    if (this._currentTime != widget.amountOfTime) {
      this._changeTimeAnimation();
    }

    return new AnimatedBuilder(
      animation: this._animation,
      builder: (BuildContext context, Widget child) {
        final Matrix4 transform = new Matrix4.identity()
          ..scale(1.0, this._animation.value, 1.0);
        return new Transform(
          transform: transform,
          alignment: FractionalOffset.center,
          child: child,
        );
      },
      child: new Text(
        this._currentTime,
        textAlign: TextAlign.left,
        style: new TextStyle(fontSize: 100.0),
      ),
    );
  }

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

在时间变化期间产生以下效果:

【讨论】:

    【解决方案2】:

    您应该在 AnimationController 上调用 .reset(),或者在构建方法中调用 .forward() change into .forward(from: 0.0)) 时传入 from 参数。在 Animationcontroller 上调用 .forward() 会将其移动到上限。再次调用.forward(),而不重置或传入“from”,会导致它什么也不做,因为您已经处于最大值(uppebound)。

    【讨论】:

    • 当我这样做时,我得到以下异常:Another exception was thrown: setState() or markNeedsBuild() called during build. 我相信我太频繁地改变状态并且会改变它。编辑:1分钟后更新后我仍然得到异常
    • 我以前没有使用过 redux,但这里有一个没有 redux 的工作解决方案的要点(拿走了你的代码并基本上修改了它),我只是在动画运行一次的情况下增加一个计数器每 1 秒一次,没有任何问题。 gist.github.com/mattiasLundell/b62eb1034ab1204fa2ee5d6a2a0d3671。希望对您有所帮助。
    猜你喜欢
    • 2018-04-22
    • 1970-01-01
    • 2011-03-22
    • 2019-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多