Flutter(十五)——動畫的封裝與簡化

前言

在上一篇的動畫內容中,我們學習了基本的概念,以及動畫的基本使用規則,但是,上一篇的代碼真的實際項目中應用很多嗎?其實不是,上一篇之所以那麼介紹,只是爲了讓大家更瞭解Flutter動畫的原理,其實還有更簡單封裝與簡化的使用方式,這一篇就開始學習這些內容。

AnimatedWidget

前面動畫之中,我們都是通過addListener和setState來更新UI的,然而有時候可以不用這麼麻煩,通過AnimationWidget這個類就可以實現,它對addListener和setState進行了封裝,隱藏了實現細節。下面,我們直接上代碼來看看:

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
  Animation<double> animation;
  AnimationController controller;

  initState(){
    super.initState();
    controller=AnimationController(duration: const Duration(milliseconds: 2000),vsync: this);
    animation=CurvedAnimation(parent: controller,curve: Curves.bounceIn)..addStatusListener((status){
      if(status==AnimationStatus.completed){//動畫在結束時停止的狀態
        controller.reverse();//顛倒
      }else if(status==AnimationStatus.dismissed){//動畫在開始時就停止的狀態
        controller.forward();//向前
      }
    })..addListener((){
      setState(() {
        print(animation.value);
      });
    });
    controller.forward();
  }

  @override
  void dispose() {
    controller.dispose();
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimationLogo(animation: animation,);
  }
}

class AnimationLogo extends AnimatedWidget{

  AnimationLogo({Key key,Animation<double> animation})
      :super(key:key,listenable:animation);

  @override
  Widget build(BuildContext context) {
    final Animation<double> animation=listenable;
    return Scaffold(
      appBar: AppBar(
        title: Text("封裝動畫"),
      ),
      body: Container(
        height: animation.value*300,
        margin: EdgeInsets.symmetric(vertical: 10.0),
        width: animation.value*300,
        child: FlutterLogo(),
      ),
    );
  }

}

封裝後,AnimationLogo可以通過當前自身Animation的value值來繪製自己。

AnimatedBuilder

有時候我們會使用多個AnimatedWidget,而如果多次實現AnimatedWidget,則代碼就顯得不那麼美觀了,這個時候,我們就需要考慮使用AnimatedBuilder,它的優點有:

(1)不需要知道如何渲染組件,也不需要知道如何管理動畫對象

(2)繼承自AnimatedWidget,可以直接當作組件來使用,且不用顯式地去添加幀的監聽addListener(…),然後在調用setState

(3)只調用動畫組件中地build,在複雜地佈局下性能有所提高

我們先來看一張組件示意圖:

組件
接着我們將上面的代碼進行重構,代碼如下:

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
  Animation<double> animation;
  AnimationController controller;

  initState(){
    super.initState();
    controller=AnimationController(duration: const Duration(milliseconds: 2000),vsync: this);
    animation=CurvedAnimation(parent: controller,curve: Curves.bounceIn)..addStatusListener((status){
      if(status==AnimationStatus.completed){//動畫在結束時停止的狀態
        controller.reverse();//顛倒
      }else if(status==AnimationStatus.dismissed){//動畫在開始時就停止的狀態
        controller.forward();//向前
      }
    })..addListener((){
      setState(() {
      });
    });
    controller.forward();
  }

  @override
  void dispose() {
    controller.dispose();
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GrowTransition(child:AnimationLogo(),animation: animation,);
  }
}

class AnimationLogo extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      margin: EdgeInsets.symmetric(vertical: 10),
      child: FlutterLogo(),
    );
  }
}

class GrowTransition extends StatelessWidget{
  final Widget child;
  final Animation<double> animation;
  GrowTransition({this.child,this.animation});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("AnimatedBuilder"),),
      body: Center(
        child: AnimatedBuilder(
          animation: this.animation,
          builder: (BuildContext context,Widget child){
            return Container(
              height: animation.value*300,
              width: animation.value*300,
              child: child,
            );
          },
          child: this.child,
        ),
      ),
    );
  }
}

前面的代碼基本一樣,就是後面的代碼變更了,所以重點看後面的代碼就行。其實在Flutter開發中,通過AnimatedBuilder方式還封裝了很多動畫,比如SizeTransition,ScaleTransition,RotationTransition,FadeTransition,FractionalTranslation等。很多時候我們都可以反覆使用這些預置的過渡類。效果圖更前篇文章差不多,這裏就不展示了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章