Flutter(6)-動畫(平移/縮放/旋轉(zhuǎn)/Alpha)

本篇簡單介紹下在Flutter中動畫的實現(xiàn)以及示例平移、縮放、旋轉(zhuǎn)和alpha動畫。

1.動畫相關(guān)知識介紹

在Flutter中Widget動畫的組成有下面這些:

  • Animation:動畫庫中的一個核心類,它生成指導(dǎo)動畫的值;
  • CurvedAnimation:將動畫過程抽象為一個非線性曲線;
  • AnimationController:用來管理管理動畫,常用的方法有forward():啟動動畫;reverse({double from}:倒放動畫;reset():重置動畫,將其設(shè)置到動畫的開始位置;stop({ bool canceled = true }):停止動畫。
  • Tween:AnimationController對象的范圍從0.0到1.0。如果您需要不同的范圍或不同的數(shù)據(jù)類型,則可以使用Tween來配置動畫以生成不同的范圍或數(shù)據(jù)類型的值。

在開發(fā)的過程中我們用AnimatedWidget與AnimatedBuilder可以更簡練的方便我們對Widget進行動畫的操作:

  • AnimatedWidget :使用它可以簡化我們對動畫的使用,在不使用AnimatedWidget的情況下需要手動調(diào)用動畫的addListener(),并在回調(diào)中添加setState()才能看到動畫效果,而使用AnimatedWidget我們就可以簡化這一操作。
  • AnimatedBuilder: 用于構(gòu)建動畫的通用Widget,可以理解為是拆分動畫的一個工具類,借助它我們可以將動畫和widget進行分離,更加的好管理。
2.平移動畫

我們直接用SlideTransition來一個平移動畫示例:

import 'package:flutter/material.dart';

class BoxMoveAnimation extends StatefulWidget {
  BoxMoveAnimation({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _BoxMoveAnimationState createState() => _BoxMoveAnimationState();
}

class _BoxMoveAnimationState extends State<BoxMoveAnimation> with TickerProviderStateMixin {

  AnimationController controller;
  Animation<Offset> animation;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Container(
        //SlideTransition 用于執(zhí)行平移動畫
        child: SlideTransition(
          position: animation,
          //將要執(zhí)行動畫的子view
          child: Container(
            width: 200,
            height: 200,
            color: Colors.red,
          ),
        ),
      ),
    );
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller =
        AnimationController(duration: Duration(milliseconds: 2000), vsync: this);
    controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        //AnimationStatus.completed 動畫在結(jié)束時停止的狀態(tài)
        debugPrint('完成');
        controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        //AnimationStatus.dismissed 表示動畫在開始時就停止的狀態(tài)
        debugPrint('消失');
        controller.forward();
//        controller.dispose();
      }
    });
    animation =
        Tween(begin: Offset.zero, end: Offset(1.0, 0.0)).animate(controller);
    //開始執(zhí)行動畫
    controller.forward();
  }
}

看一下運行效果:


可以看到我們利用SlideTransition來做平移動畫還是非常方便的,直接將animation設(shè)置為position屬性就可以了。

3.縮放動畫

直接用ScaleTransition來一個縮放動畫的示例:

class BoxScaleAnimation extends StatefulWidget {
  BoxScaleAnimation({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _BoxScaleAnimationState createState() => _BoxScaleAnimationState();
}

class _BoxScaleAnimationState extends State<BoxScaleAnimation> with TickerProviderStateMixin {
  AnimationController controller;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller =
        AnimationController(duration: const Duration(seconds: 2), vsync: this);
    controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        print("completed");
        controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        print("dismissed");
        controller.forward();
      } else if (status == AnimationStatus.forward) {
        print("forward");
      } else if (status == AnimationStatus.reverse) {
        print("reverse");
      }
    });
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        appBar: AppBar(title: Text(widget.title)),
        body:Center(
          child: ScaleTransition(
            alignment: Alignment.center,
            scale: controller,
            child: Container(
              width: 200,
              height: 200,
              color: Colors.blue,
            ),
          ),
        ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }
}

看一下運行效果:


4.旋轉(zhuǎn)動畫

RotationTransition來一個縮放動畫的示例:

class BoxRotationAnimation extends StatefulWidget {
  BoxRotationAnimation({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _BoxRotationAnimationState createState() => _BoxRotationAnimationState();
}

class _BoxRotationAnimationState extends State<BoxRotationAnimation> with TickerProviderStateMixin {

  AnimationController controller;
  Animation animation;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller =
        AnimationController(duration: const Duration(seconds: 3), vsync: this);
    animation =
        Tween(begin: 0.0, end: 0.25).animate(controller);
    controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        print("completed");
        controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        print("dismissed");
        controller.forward();
      } else if (status == AnimationStatus.forward) {
        print("forward");
      } else if (status == AnimationStatus.reverse) {
        print("reverse");
      }
    });
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body:Center(
        child: RotationTransition(
          alignment: Alignment.center,
          turns: animation,
          child: Container(
            width: 160,
            height: 160,
            color: Colors.green,
            child: Center(
              child: Text('Box'),
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }
}

看一下運行效果:


旋轉(zhuǎn)的動畫中我們對動畫的旋轉(zhuǎn)的值進行了限制,默認的情況下旋轉(zhuǎn)角度是360°,代碼限制到了0.25也就是90°。就像前面說的Animation用來生成指導(dǎo)動畫的值。

5.Opacity動畫

FadeTransition來一個Opacity動畫的示例:

class BoxOpacityAnimation extends StatefulWidget {
  BoxOpacityAnimation({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _BoxOpacityAnimationState createState() => _BoxOpacityAnimationState();
}

class _BoxOpacityAnimationState extends State<BoxOpacityAnimation> with TickerProviderStateMixin {

  AnimationController controller;
  Animation animation;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller =
        AnimationController(duration: const Duration(seconds: 2), vsync: this);
    animation =
        Tween(begin: 0.0, end: 1.0).animate(controller);
    controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        print("completed");
        controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        print("dismissed");
        controller.forward();
      } else if (status == AnimationStatus.forward) {
        print("forward");
      } else if (status == AnimationStatus.reverse) {
        print("reverse");
      }
    });
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body:Center(
        child: FadeTransition(
          opacity: animation,
          child: Container(
            width: 160,
            height: 160,
            color: Colors.green,
            child: Center(
              child: Text('Box'),
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }
}

看一下運行效果:


通過以上示例,我們會發(fā)現(xiàn)官方給我們封裝的AnimatedWidget的確非常的方便,能夠滿足我們一般的動畫需求,這里必須列一下Flutter中文網(wǎng)的動畫介紹,里面的Hero 動畫是一個非常好的示例,系統(tǒng)封裝的動畫Widget非常好用,可以自己去看看,Animatedbuilder的使用可以點擊這里直接看到,文中所有的代碼都可以在Github:BoxJ/Flutter-daydayup中下載,本篇代碼的文件夾是boxdemo_006,歡迎一起交流!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容