Flutter 重建 TweenAnimationBuilder

问题描述 投票:0回答:2

我想用TweenAnimationBuilder制作一个翻转动画,一个容器会翻转并改变颜色。我想添加一个按钮,当用户点击它时,容器会再次翻转并变成另一种颜色。

这是我的代码:

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  bool isBack = true;

  Color backColor = Colors.green;
  Color topColor = Colors.red;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              box(),
              SizedBox(height: 10),
              ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    minimumSize: Size(25, 10),
                    elevation: 10,
                  ),
                  onPressed: () {
                    setState(() {
                      backColor = Colors.red;
                      topColor = Colors.blue;
                    });
                  },
                  child:
                      Text('change to blue', style: TextStyle(fontSize: 16))),
            ],
          ),
        ),
      ),
    );
  }

  Widget box() {
    print('building');
    return TweenAnimationBuilder(
        tween: Tween<double>(begin: 0, end: pi),
        duration: Duration(seconds: 1),
        builder: (BuildContext context, double value, _) {
          print(value);
          if (value >= (pi / 2)) {
            isBack = false;
          } else {
            isBack = true;
          }
          return (Transform(
            alignment: Alignment.center,
            transform: Matrix4.identity()
              ..setEntry(3, 2, 0.001)
              ..rotateY(value),
            child: Container(
                width: 100,
                height: 100,
                child: isBack
                    ? Container(
                        color: backColor,
                      )
                    : Transform(
                        alignment: Alignment.center,
                        transform: Matrix4.identity()
                          ..rotateY(
                              pi),
                        child: Container(
                          color: topColor,
                        ),
                      ) 
                ),
          ));
        });
  }
}

在第一次构建时,补间值将从头开始:

building
0
0
0
0.13080335172486462
0.19619246121668257
0.2180893620122034
...
3.141592653589793

但是当我点击按钮改变颜色时,它不会从开始值重新开始,它只是停留在3.14:

building
3.141592653589793

现在按钮只会改变容器的颜色,但不会再次翻转。

我想在 setstate 函数之后,补间值会再次从 0 重新开始,为什么不会这样做呢? 有人可以解释一下吗?

flutter flutter-animation
2个回答
0
投票

您只需要一个

AnimationController
AnimatedBuilder
来控制动画。

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  bool isBack = true;

  Color backColor = Colors.blue;
  Color topColor = Colors.red;
  late AnimationController _animationController;
  late Animation _rotationAnimation;
  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: const Duration(seconds: 1));

    _rotationAnimation =
        Tween<double>(begin: 0, end: pi).animate(_animationController);

     _animationController.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              box(),
              SizedBox(height: 10),
              ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    minimumSize: Size(25, 10),
                    elevation: 10,
                  ),
                  onPressed: () {
                    setState(() {
                      backColor = Colors.red;
                      topColor = Colors.blue;
                    });
                    // if (_animationController.isDismissed) {
                    //   _animationController.forward();
                    // } else if (_animationController.isCompleted) {
                    //   _animationController.reverse();
                    // }
                    _animationController.forward(from: 0.0);
                  },
                  child:
                      Text('change to blue', style: TextStyle(fontSize: 16))),
            ],
          ),
        ),
      ),
    );
  }

  Widget box() {
    return AnimatedBuilder(
        animation: _animationController,
        // tween: Tween<double>(begin: 0, end: pi),
        // duration: Duration(seconds: 1),
        builder: (_, __) {
          // print(value);
          if (_rotationAnimation.value >= (pi / 2)) {
            isBack = false;
          } else {
            isBack = true;
          }
          return Transform(
            alignment: Alignment.center,
            transform: Matrix4.identity()
              ..setEntry(3, 2, 0.001)
              ..rotateY(_rotationAnimation.value),
            child: Container(
              width: 100,
              height: 100,
              child: isBack
                  ? Container(
                      color: backColor,
                    )
                  : Transform(
                      alignment: Alignment.center,
                      transform: Matrix4.identity()..rotateY(pi),
                      child: Container(
                        color: topColor,
                      ),
                    ),
            ),
          );
        });
  }
}

0
投票

您只需为 TweenAnimationBuilder 提供一个键即可。

TweenAnimationBuilder<T>(
         key: UniqueKey(),
         duration: const Duration(milliseconds: 700),

您的情况的原因是:Flutter 没有为新的 TweenAnimationBuilder 小部件创建新元素,这是为了性能。

© www.soinside.com 2019 - 2024. All rights reserved.