Flutter 在flatter中,我如何更改一些小部件并将其设置为新的大小?

Flutter 在flatter中,我如何更改一些小部件并将其设置为新的大小?,flutter,flutter-animation,Flutter,Flutter Animation,我想改变一些小部件的子部件,然后看到它动画到新的子部件的高度,也有一个淡入淡出过渡 我可以用AnimatedCrossFade,但是我必须同时保留firstChild和secondChild,我不能这样做 如果我使用AnimatedSwitcher,它可以让我简单地更改它的子对象,但是它只设置淡入淡出的动画,而不设置大小 AnimatedContainer也不起作用,因为我事先不知道孩子们的大小 是否有一些我缺少的小部件可以满足我的需要,如果没有,我如何在不使用AnimationControll

我想改变一些小部件的子部件,然后看到它动画到新的子部件的高度,也有一个淡入淡出过渡

我可以用
AnimatedCrossFade
,但是我必须同时保留
firstChild
secondChild
,我不能这样做

如果我使用
AnimatedSwitcher
,它可以让我简单地更改它的子对象,但是它只设置淡入淡出的动画,而不设置大小

AnimatedContainer
也不起作用,因为我事先不知道孩子们的大小


是否有一些我缺少的小部件可以满足我的需要,如果没有,我如何在不使用
AnimationController
s的情况下做到这一点?

实现这一点的方法有很多。这只是一个例子:

  class LogoApp extends StatefulWidget {
    _LogoAppState createState() => _LogoAppState();
  }

  class _LogoAppState extends State<LogoApp> with TickerProviderStateMixin {
    Animation animation;
    Animation animationOpacity;
    AnimationController controller;

    initState() {
      super.initState();
      controller = AnimationController(
          duration: const Duration(milliseconds: 2000), vsync: this);
      final CurvedAnimation curve =
          CurvedAnimation(parent: controller, curve: Curves.easeIn);
      animation = Tween(begin: 0.0, end: 300.0).animate(curve);
      animationOpacity = Tween(begin: 0.0, end: 1.0).animate(curve);
      controller.forward();
    }

    Widget build(BuildContext context) {
      return AnimatedBuilder(
        animation: controller,
        builder: (context, widget) {
          return Opacity(
            opacity: animationOpacity.value,
                    child: Container(
              margin: EdgeInsets.symmetric(vertical: 10.0),
              height: animation.value,
              width: animation.value,
              child: FlutterLogo(),
            ),
          );
        },
      );
    }

    dispose() {
      controller.dispose();
      super.dispose();
    }
  }
请参阅本文档

已更新

  class LogoApp extends StatefulWidget {
    _LogoAppState createState() => _LogoAppState();
  }

  class _LogoAppState extends State<LogoApp> with TickerProviderStateMixin {
    Animation controllerAnimation;
    AnimationController controller;

    initState() {
      super.initState();
      controller = AnimationController(
          duration: const Duration(milliseconds: 1000), vsync: this);
      final CurvedAnimation curve =
          CurvedAnimation(parent: controller, curve: Curves.easeIn);
      controllerAnimation = Tween(begin: 0.0, end: 1.0).animate(curve);
      controller.forward();
    }

    bool isSelected = false;

    Widget build(BuildContext context) {
      return Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          AnimatedSwitcher(
            duration: Duration(seconds: 10),//it is ignored
            child: isSelected
                ? Container(
                    width: 200.0,
                    height: 200.0,
                    child: FlutterLogo(
                      colors: Colors.red,
                    ),
                  )
                : Container(
                    width: 200.0,
                    height: 200.0,
                    child: FlutterLogo(
                      colors: Colors.blue,
                    )),
            transitionBuilder: defaultTransitionBuilder,
          ),
          MaterialButton(
            child: Text("Texting"),
            onPressed: () {
              if (controller.isCompleted) {
                controller.reset();
              }

              controller.forward();

              setState(() {
                isSelected = !isSelected;
              });
            },
          )
        ],
      );
    }

    Widget defaultTransitionBuilder(Widget child, Animation<double> animation) {
      return AnimatedBuilder(
        animation: controller,
        builder: (context, widget) {
          return Opacity(
            opacity: controllerAnimation.value,
            child: ScaleTransition(
              scale: controllerAnimation,
              child: widget,
            ),
          );
        },
        child: child,
      );
    }

    dispose() {
      controller.dispose();
      super.dispose();
    }
  }
class LogoApp扩展StatefulWidget{
_LogoAppState createState()=>\u LogoAppState();
}
类_LogoAppState使用TickerProviderStateMixin扩展状态{
动画控制器;
动画控制器;
initState(){
super.initState();
控制器=动画控制器(
持续时间:常量持续时间(毫秒:1000),vsync:this;
最终曲线化曲线=
曲线动画(父对象:控制器,曲线:Curves.easeIn);
controllerAnimation=Tween(开始:0.0,结束:1.0)。设置动画(曲线);
controller.forward();
}
bool-isSelected=false;
小部件构建(构建上下文){
返回列(
crossAxisAlignment:crossAxisAlignment.center,
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
动画切换器(
持续时间:持续时间(秒数:10),//忽略它
孩子:我当选了
?容器(
宽度:200.0,
高度:200.0,
孩子:我的标志(
颜色:颜色,红色,
),
)
:容器(
宽度:200.0,
高度:200.0,
孩子:我的标志(
颜色:颜色,蓝色,
)),
transitionBuilder:defaultTransitionBuilder,
),
材料按钮(
儿童:文本(“文本”),
已按下:(){
如果(控制器已完成){
controller.reset();
}
controller.forward();
设置状态(){
isSelected=!isSelected;
});
},
)
],
);
}
小部件defaultTransitionBuilder(小部件子部件、动画){
返回动画生成器(
动画:控制器,
生成器:(上下文,小部件){
返回不透明度(
不透明度:controllerAnimation.value,
子:ScaleTransition(
比例:控制器激活,
孩子:小部件,
),
);
},
孩子:孩子,
);
}
处置{
controller.dispose();
super.dispose();
}
}

这就解决了问题:

它同时淡入淡出并设置大小动画,而不必指定两个子对象。还可以分别为淡入度和大小定义持续时间和曲线

像这样使用它:

bool toggle=true; 
Widget widget1 = ...;
Widget widget2 = ...;

AnimatedSizeAndFade(
    vsync: this,
    child: toggle ? widget1 : widget2,
),
注意:如果要使用上述代码,请务必阅读文档:

  • “旧”和“新”子对象必须具有相同的宽度,但可以具有不同的高度

  • 如果“新”子项与“旧”子项是相同的小部件类型,但参数不同,则
    AnimatedSizeAndFade
    不会在它们之间进行转换,因为就框架而言,它们是相同的小部件,并且可以使用新参数更新现有小部件。要强制进行转换,请设置一个
    (通常是
    值键
    ,获取任何小部件数据,这些数据将改变您希望被视为唯一的每个子小部件上小部件的视觉外观


这是一个可运行的示例:

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

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  bool toggle;

  @override
  void initState() {
    super.initState();
    toggle = false;
  }

  @override
  Widget build(BuildContext context) {
    var toggleButton = Padding(
      padding: const EdgeInsets.all(8.0),
      child: MaterialButton(
        child: const Text("Toggle"),
        color: Colors.grey,
        onPressed: () {
          setState(() {
            toggle = !toggle;
          });
        },
      ),
    );

    var widget1 = Container(
      key: ValueKey("first"),
      color: Colors.blue,
      width: 200.0,
      child: const Text(
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt "
            "ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
            "ullamco laboris nisi ut aliquip ex ea commodo consequat.",
      ),
    );

    var widget2 = Container(
      key: ValueKey("second"),
      color: Colors.red,
      width: 200.0,
      child: const Text(
        "I am ready for my closeup.",
      ),
    );

    return MaterialApp(
      home: Material(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(height: 100.0),
            toggleButton,
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text("Some text above."),
                AnimatedSizeAndFade(
                  vsync: this,
                  child: toggle ? widget1 : widget2,
                  fadeDuration: const Duration(milliseconds: 300),
                  sizeDuration: const Duration(milliseconds: 600),
                ),
                const Text("Some text below."),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
导入“包装:颤振/材料.省道”;
导入“package:widgets/widgets.dart”;
void main(){
runApp(MyApp());
}
类MyApp扩展了StatefulWidget{
@凌驾
_MyAppState createState()=>\u MyAppState();
}
类MyAppState使用TickerProviderStateMixin扩展状态{
布尔开关;
@凌驾
void initState(){
super.initState();
切换=假;
}
@凌驾
小部件构建(构建上下文){
var-toggleButton=填充(
填充:常数边集全部(8.0),
子:材质按钮(
子项:常量文本(“切换”),
颜色:颜色。灰色,
已按下:(){
设置状态(){
切换=!切换;
});
},
),
);
var widget1=容器(
key:ValueKey(“第一”),
颜色:颜色,蓝色,
宽度:200.0,
子:常量文本(
“Lorem ipsum Door sit amet,一位杰出的献身者,他是一位临时顾问”
“我们的劳动和生活是巨大的,我们的生活是微小的,我们的工作是实践的”
“ullamco laboris nisi ut aliquip ex ea commodo consequat.”,
),
);
var widget2=容器(
key:ValueKey(“第二”),
颜色:颜色,红色,
宽度:200.0,
子:常量文本(
“我准备好特写了。”,
),
);
返回材料PP(
家:材料(
孩子:排(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
容器(高度:100.0),
切换按钮,
纵队(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
常量文本(“上面的一些文本”),
动画大小和外观(
import 'package:flutter/material.dart';
import 'package:widgets/widgets.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  bool toggle;

  @override
  void initState() {
    super.initState();
    toggle = false;
  }

  @override
  Widget build(BuildContext context) {
    var toggleButton = Padding(
      padding: const EdgeInsets.all(8.0),
      child: MaterialButton(
        child: const Text("Toggle"),
        color: Colors.grey,
        onPressed: () {
          setState(() {
            toggle = !toggle;
          });
        },
      ),
    );

    var widget1 = Container(
      key: ValueKey("first"),
      color: Colors.blue,
      width: 200.0,
      child: const Text(
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt "
            "ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
            "ullamco laboris nisi ut aliquip ex ea commodo consequat.",
      ),
    );

    var widget2 = Container(
      key: ValueKey("second"),
      color: Colors.red,
      width: 200.0,
      child: const Text(
        "I am ready for my closeup.",
      ),
    );

    return MaterialApp(
      home: Material(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(height: 100.0),
            toggleButton,
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text("Some text above."),
                AnimatedSizeAndFade(
                  vsync: this,
                  child: toggle ? widget1 : widget2,
                  fadeDuration: const Duration(milliseconds: 300),
                  sizeDuration: const Duration(milliseconds: 600),
                ),
                const Text("Some text below."),
              ],
            ),
          ],
        ),
      ),
    );
  }
}