Flutter重建TweenAnimationBuilder

0pizxfdo  于 2023-11-21  发布在  Flutter
关注(0)|答案(2)|浏览(136)

我想用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函数之后,tween值将重新开始,为什么它不会这样做?有人能解释一下吗?

mo49yndu

mo49yndu1#

你只需要一个AnimationControllerAnimatedBuilder来控制动画。

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

字符串

u4dcyp6a

u4dcyp6a2#

你可以只给给予一个键到TweenAnimationBuilder。

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

字符串
在你的例子中,原因是:Flutter没有为新的TweenAnimationBuilder小部件创建新元素,这是为了性能。

相关问题