美文网首页
Flutter 之 动画2

Flutter 之 动画2

作者: Cat_uncle | 来源:发表于2022-03-13 14:56 被阅读0次

    在为 Widget 添加动画效果的过程中我们不难发现,Animation 仅提供动画的数据,因此我们还需要监听动画执行进度,并在回调中使用 setState 强制刷新界面才能看到动画效果。考虑到这些步骤都是固定的,Flutter 提供了两个类来帮我们简化这一步骤,即 AnimatedWidget 与 AnimatedBuilder。

    AnimatedWidget

    class WidgetAnimateWidget extends StatefulWidget {

    @override

      StatecreateState()=>_WidgetAnimateWidgetState();

    }

    class _WidgetAnimateWidgetState extends Statewith SingleTickerProviderStateMixin {

    AnimationController?controller;

    late Animation animation;

    @override

      void initState() {

    super.initState();

    // 创建动画周期为1秒的AnimationController对象

        controller =AnimationController(

    vsync:this, duration:const Duration(milliseconds:3000));

    final CurvedAnimation curve =CurvedAnimation(

    parent:controller!, curve:Curves.easeIn);

    // 创建从50到200线性变化的Animation对象

        animation =Tween(begin:10.0, end:200.0).animate(curve);

    // 启动动画

        controller!.repeat(reverse:true);

    }

    @override

      Widget build(BuildContext context) {

    return MaterialApp(

    home:Scaffold(

    body:AnimatedLogo(animation:animation,)

    ));

    }

    @override

      void dispose() {

    // 释放资源

        controller!.dispose();

    super.dispose();

    }

    }

    class AnimatedLogo extends AnimatedWidget {

    AnimatedLogo({Key? key,required Animation animation})

    :super(key: key, listenable: animation);

    Widget build(BuildContext context) {

    Animation animation =listenable as Animation;

    return Center(

    child:Container(

    height:animation.value,

    width:animation.value,

    child:FlutterLogo(),

    ),

    );

    }

    }

    在 AnimatedLogo 的 build 方法中,我们使用 Animation 的 value 作为 logo 的宽和高。这样做对于简单组件的动画没有任何问题,但如果动画的组件比较复杂,一个更好的解决方案是,将动画和渲染职责分离:logo 作为外部参数传入,只做显示;而尺寸的变化动画则由另一个类去管理。这个分离工作,我们可以借助 AnimatedBuilder 来完成。与 AnimatedWidget 类似,AnimatedBuilder 也会自动监听 Animation 对象的变化,并根据需要将该控件树标记为 dirty 以自动刷新 UI。

    class BuilderAnimateWidget extends StatefulWidget {

    @override

      StatecreateState() {

    return _BuilderAnimateState();

    }

    }

    class _BuilderAnimateState extends Statewith SingleTickerProviderStateMixin {

    late AnimationController controller;

    late Animationanimation;

    @override

      void initState() {

    super.initState();

    // 创建动画周期为1秒的AnimationController对象

        controller =AnimationController(

    vsync:this, duration:const Duration(milliseconds:3000));

    final CurvedAnimation curve =CurvedAnimation(

    parent:controller, curve:Curves.easeInOut);

    // 创建从50到200线性变化的Animation对象

        animation =Tween(begin:10.0, end:200.0).animate(curve);

    // 启动动画

        controller.repeat(reverse:true);

    }

    @override

      Widget build(BuildContext context) {

    return MaterialApp(

    home:Scaffold(

    body:Center(

    child:AnimatedBuilder(

    animation:animation,

    //child:FlutterLogo(),

                        builder: (context, child) =>Container(

    width:animation.value,

    height:animation.value,

    child:FlutterLogo(),

    )

    )

    )

    ));

    }

    @override

      void dispose() {

    // 释放资源

        controller.dispose();

    super.dispose();

    }

    }

    hero 动画

    通过 Hero,我们可以在两个页面的共享元素之间,做出流畅的页面切换效果。

    为了实现共享元素变换,我们需要将这两个组件分别用 Hero 包裹,并同时为它们设置相同的 tag “hero”。

    class Page2 extends StatelessWidget {

    Widget build(BuildContext context) {

    return  Scaffold(

    appBar:AppBar(title:Text('Page1'),),

    body:GestureDetector(

    child:Row(children: [

    Hero(

    tag:'hero',// 设置共享 tag

                    child:Container(

    width:100, height:100,

    child:FlutterLogo())

    ),

    Text('点击Logo查看Hero效果')

    ],),

    onTap: () {

    Navigator.of(context).push(MaterialPageRoute(builder: (_)=>Page2()));

    },

    )

    );

    }

    }

    class Page2 extends StatelessWidget {

    @override

      Widget build(BuildContext context) {

    return  Scaffold(

    appBar:AppBar(title:Text('Page2'),),

    body:Hero(

    tag:'hero',// 设置共享 tag

                child:Container(

    width:300, height:300,

    child:FlutterLogo()

    ))

    );

    }

    }

    相关文章

      网友评论

          本文标题:Flutter 之 动画2

          本文链接:https://www.haomeiwen.com/subject/izbqdrtx.html