Flutter 動畫(一)

簡介

  • Flutter動畫核心類:Animation類,它可以判斷當前動畫的狀態(開始,停止,移動,前進,反向),它是由AnimationController管理的,並通過Listeners和StatusListeners管理動畫狀態的所發生的變化,我們先對動畫有了大體的瞭解,下面我們對其中提到的類進行逐一學習
  • 這次主要學習flutter動畫中的 平移,縮放,旋轉,透明度,插值器,是爲之後的自定義動畫做準備嗷!

Animation

  • Animation對象本身隨手記屏幕是無感知的,,它僅僅直到當前動畫的插值和狀態,,Animation對象是一個在一段時間內,一次生成一個區間值的類,其輸出值可以是線性的、非線性的,控制器可以控制Animation的動畫方式:正向、反向、中間進行切換。

Animatable

  • Animatable是控制動畫類型的類,比如我們需要控制動畫過程中顏色值的變化,那麼Animatable就用來控制色值的變化

AnimationController

  • 上面提到的動畫控制器即AnimationController,它負責在給定的時間段內,以線性的方式生成默認區間爲(0.0, 1.0)的數字,我們可以通過AnimationController來創建Animation對象
// vsync: 該參數接受的是TickerProvidr(宿主)類型的對象,作用是阻止在屏幕鎖屏時執行動畫以避免不必要的資源浪費
AnimationController _controller = AnimationController(vsync: this, duration: duration)
AnimationController 的常用操作說明
屬性 說明
controller.forward() 正向開始執行動畫
controller.reverse() 反向開始執行動畫
controller.reset() 重置動畫到初始狀態
controller.dispose() 取消/停止動畫
AnimationStatus 動畫狀態說明
屬性 說明
AnimationStatus.forward 執行controller.forward() 會回調此狀態
AnimationStatus.reverse 執行controller.reverse() 會回調此狀態
AnimationStatus.dismissed 動畫從controller.reverse() 反向執行 結束時會回調此方法
AnimationStatus.completed 動畫從controller.forward() 正向執行 結束時會回調此方法

Tween補間動畫

  • 通常AnimationController的取值範圍是(0.0,1.0), 但是有些時候我們呢可能會需要不同範圍或者類型的值,就需要使用Tween來定義並生成相應的值,例如:
// 縮放取值變化範圍(1.0, 0.8)
Animation<double> _scaleAnimation = _scaleAnimation = Tween<double>(begin: 1, end: 0.8).animate(_controller);
  • 釋義:
    • Tween作用:定義從輸入範圍(左區間)到輸出範圍(右區間)的映射
    • Tween繼承自Animatable,例如上面的例子隨着動畫改變色值:
final Tween _colorTween = ColorTween(begin : Colors.transparent, end:Colors.black54);
示例實現平移補間動畫

import 'package:flutter/material.dart';


class SlideTransitionAnimationWidget extends StatefulWidget {
  @override
  SlideTransitionAnimationWidgetState createState() => new SlideTransitionAnimationWidgetState();
}


class SlideTransitionAnimationWidgetState extends State<SlideTransitionAnimationWidget>
    with SingleTickerProviderStateMixin {
  final Duration _duration = const Duration(milliseconds: 300);
  AnimationController _controller;
  Animation<Offset> _animation;


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SlideTransition'),
      ),
      body: Center(
        child: SlideTransition(
          position: _animation,
          child: Container(
            height: 100,
            width: 100,
            color: Colors.black,
          ),
        ),
      ),
    );
  }


  @override
  void initState() {
    _controller = AnimationController(vsync: this, duration: _duration);
    _animation = Tween<Offset>(begin: Offset(-1, 0), end: Offset(0, 0))
        .animate(_controller)
          ..addListener(() {
            // AnimationController產生的數值取決於屏幕刷新情況,一秒60幀
            // 數值生成之後,每個Animation對象都會通過Listener進行回調,下面實現動畫監聽
            setState(() {
              print(_animation.value);
            });
          })
          ..addStatusListener((status) {
            // 實現動畫循環
            if (status == AnimationStatus.completed) {
              // 正向結束時回調
              _controller.reverse();
            } else if (status == AnimationStatus.dismissed) {
              // 反向執行 結束時會回調此方法
              _controller.forward();
            }
          });
    _controller.forward();
  }


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

在這裏插入圖片描述

示例實現縮放動畫
添加
// 聲明處:
Animation<double> _scaleAnimation;
// initState中
_scaleAnimation = Tween<double>(begin: 1.0, end: 
0.5).animate(_controller);

// build中修改
body: Center(
  child: ScaleTransition(
    scale: _scaleAnimation,
    child: Container(
      height: 100,
      width: 100,
      color: Colors.black,
    ),
  ),
),

在這裏插入圖片描述

  • 實現方式都是相同的,大家可以再嘗試旋轉以及透明效果
    在這裏插入圖片描述

Curve

  • Curve類似於Android中的插值器,插值器如果不瞭解可以看一下這篇文章
  • 通過Curve,可以將動畫過程設置爲線性或者非線性,初始化如下:
final Curanimation curve = CurveAnimation(parent:controller, curve:Curves/easeIn);
示例將彈跳的插值器和透明度結合

import 'package:flutter/material.dart';


class SlideTransitionAnimationWidget extends StatefulWidget {
  @override
  SlideTransitionAnimationWidgetState createState() => new SlideTransitionAnimationWidgetState();
}


class SlideTransitionAnimationWidgetState extends State<SlideTransitionAnimationWidget>
    with SingleTickerProviderStateMixin {
  final Duration _duration = const Duration(milliseconds: 3000);
  AnimationController _controller;
  Animation<Offset> _slideAnimation;
  Animation<double> _scaleAnimation;
  Animation<double> _fadeAnimation;
  Animation<double> _rotationAnimation;
  Animation<double> _curveAnimation;
  final _opacityTween = Tween<double>(begin: 0.1 ,end: 1.0);


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SlideTransition'),
      ),
      body: Center(
        // 做相應動畫可以直接修改此處,看下源碼動畫的參數是什麼即可
        child: Opacity(
          // 計算差值,就相當於在自定義的插值器前面設置一個數值轉換器
          // 將透明度的設置和彈跳的插值器結合,evaluate作用是使得彈跳的進度即爲透明度設置的進度
          opacity : _opacityTween.evaluate(_curveAnimation),
          child: Container(
            height: 100,
            width: 100,
            color: Colors.black,
          ),
        ),
      ),
    );
  }


  @override
  void initState() {
    _controller = AnimationController(vsync: this, duration: _duration);
    _scaleAnimation = Tween<double>(begin: 1.0, end: 0.5).animate(_controller);
    _fadeAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(_controller);
    _rotationAnimation = Tween<double>(begin: 0.0, end: 60.0).animate(_controller);
    _curveAnimation = CurvedAnimation(parent: _controller, curve: Curves.bounceIn);
    _slideAnimation = Tween<Offset>(begin: Offset(-1, 0), end: Offset(0, 0))
        .animate(_controller)
          ..addListener(() {
            // AnimationController產生的數值取決於屏幕刷新情況,一秒60幀
            // 數值生成之後,每個Animation對象都會通過Listener進行回調,下面實現動畫監聽
            setState(() {
              print(_slideAnimation.value);
            });
          })
          ..addStatusListener((status) {
            // 實現動畫循環
            if (status == AnimationStatus.completed) {
              // 正向結束時回調
              _controller.reverse();
            } else if (status == AnimationStatus.dismissed) {
              // 反向執行 結束時會回調此方法
              _controller.forward();
            }
          });
    _controller.forward();
  }


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

在這裏插入圖片描述

Demo地址

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