Flutter 學(xué)習(xí)之旅(三十四) Flutter 動(dòng)畫(一)

Flutter 中的動(dòng)畫由 Animation、Curve、Controller、Tween共同組成,每一個(gè)組件都有他們特定的職責(zé),
下面我們一個(gè)一個(gè)介紹

AnimationController

  AnimationController({
    double value,
    ///動(dòng)畫過渡時(shí)間
    this.duration,
    this.reverseDuration,
    this.debugLabel,
    ///動(dòng)畫開始的值
    this.lowerBound = 0.0,
    ///動(dòng)畫結(jié)束的值
    this.upperBound = 1.0,
    this.animationBehavior = AnimationBehavior.normal,
    ///用來改變過程中的value的
    @required TickerProvider vsync,
  })

AnimationController用于控制動(dòng)畫,它包含動(dòng)畫的正向執(zhí)行forward()、停止stop() 、反向播放 reverse()等方法。他的區(qū)間是(0~1) 不可以超過這個(gè)區(qū)間 ,并在預(yù)定時(shí)間內(nèi)將這個(gè)數(shù)據(jù)不斷的由一端過度到另一端,每一幀都會(huì)生成一個(gè)新的值,這個(gè)過度的速度是由Curve 來控制的, 屏幕每一次刷新都是一幀,每一幀都會(huì)調(diào)用 TickerProvider來刷新當(dāng)前的動(dòng)畫的過渡值,并利用這個(gè)過渡值來構(gòu)建當(dāng)前的動(dòng)畫狀態(tài)
AnimationController 可以使用addListener 可以獲取動(dòng)畫過渡的值,addStatusListener 可以監(jiān)聽狀態(tài)發(fā)生改變,
如果想要重復(fù)執(zhí)行一個(gè)正向動(dòng)畫 forward(),

  _controller
        ..value=0
        ..forward();

注意這里如果想要每次都執(zhí)行這個(gè)動(dòng)畫,必須重置這個(gè)value,這個(gè)問題困擾了我很久,
并且在widget 的dispose 的方法內(nèi)取消注冊(cè)

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

TickerProvider 用來改變過程中的value的,使用的方法是 混入到需要的widget 中,通常為 SingleTickerProviderStateMixin,具體的作用原理還不是很理解,這里只能后來再完善了

Animation

Animation 是一個(gè)抽象類,他保存了動(dòng)畫的插值和狀態(tài),他在一定時(shí)間內(nèi)依次生成Tween之間的值,獲取的這個(gè)值可以是均勻的,也可是先快后慢等 ,這是由Curve決定的 ;動(dòng)畫不僅正向運(yùn)行,也可以反向運(yùn)行,一些比較常用的Animation 類比如Animation <double> ,Animation <Size>,Animation <Color>,Animation <Offset>等,這里我們需要記住一個(gè)比較重要的知識(shí)點(diǎn),那就是Animation 存了動(dòng)畫的插值和狀態(tài),我們可以按照動(dòng)畫正向即從0~1開始執(zhí)行,如果我們想要獲取 0.5的時(shí)候的值,則使用Tween.transform 則可以獲得,這是一個(gè)非常重要的點(diǎn).

Curve

Curve是用來控制動(dòng)畫執(zhí)行的速度的,flutter 中就是利用Curve來控制這個(gè)速度,并把勻速的線性動(dòng)畫稱為
Curves.linear ,將AnimationController利用CurvedAnimation 進(jìn)行包裝,
例子

    animatedContainer = AnimationController(
        duration: Duration(seconds: 2),
        lowerBound: 0,
        upperBound: 1,
        vsync: this);

    ///改變起始值
    Animation curve =
        CurvedAnimation(parent: animatedContainer, curve: Curves.easeIn,);

Tween

默認(rèn)情況下AnimationController的數(shù)據(jù)是否0-1執(zhí)行的,但是我們需要將它放大到0-100怎么執(zhí)行呢,這里使用
Tween 改變起始值就可以了,并使用tween.animate()來獲取動(dòng)畫對(duì)象
例子

_tween=IntTween(begin: 0, end: 255)
anim=_tween.animate(_tween);

同樣可以封裝ColorTween

    tween=ColorTween(begin: widget.begin,end: widget.end) ;
    anim=tween.animate(CurvedAnimation(parent: _controller,curve: Curves.easeOut));

下面寫一個(gè)簡(jiǎn)單的例子
這個(gè)例子是控制文本的顏色Color.fromARGB(animation.value, 1, 1, 1),只需要從0-255 之間就可以了
然后先正向執(zhí)行,再反向執(zhí)行無(wú)限重復(fù)這個(gè)動(dòng)畫,

class _TsmAnimationState extends State<TsmAnimationPage>
    with SingleTickerProviderStateMixin {
  Animation<int> animation;
  AnimationController animatedContainer;

  @override
  void initState() {
    animatedContainer = AnimationController(
        duration: Duration(seconds: 2),
        lowerBound: 0,
        upperBound: 1,
        vsync: this);

    ///添加變速模型
    Animation curve =
        CurvedAnimation(parent: animatedContainer, curve: Curves.easeIn,);

     ///改變起始值
    animation = IntTween(begin: 0, end: 255).animate(curve);


   
    animatedContainer.addListener(() {
      setState(() {
        printString("value:${animation.value}");
      });
    });
    animatedContainer.addStatusListener((status) {
      if(status==AnimationStatus.completed){
        animatedContainer.reverse();
      }else if(status==AnimationStatus.dismissed){
        animatedContainer.forward();
      }
    });
    animatedContainer.forward();
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Animation 學(xué)習(xí)"),
        centerTitle: true,
      ),
      body: Container(
        child: Center(
          child: Text(
            "重復(fù)漸隱動(dòng)畫",
            style: TextStyle(
              color: Color.fromARGB(animation.value, 1, 1, 1),
            ),
          ),
        ),
      ),
    );
  }
}

效果圖


GIF 2020-9-15 9-33-51.gif

我學(xué)習(xí)flutter的整個(gè)過程都記錄在里面了
http://m.itdecent.cn/c/36554cb4c804

最后附上demo 地址

https://github.com/tsm19911014/tsm_flutter

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

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