欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android Flutter實(shí)現(xiàn)GIF動(dòng)畫效果的方法詳解

 更新時(shí)間:2022年06月20日 10:41:19   作者:島上碼農(nóng)  
如果我們想對(duì)某個(gè)組件實(shí)現(xiàn)一組動(dòng)效應(yīng)該怎么辦呢?本文將利用Android Flutter實(shí)現(xiàn)GIF動(dòng)畫效果,文中的示例代碼講解詳細(xì),需要的可以參考一下

前言

我們之前介紹了不少有關(guān)動(dòng)畫的篇章。前面介紹的動(dòng)畫都是只有一個(gè)動(dòng)畫效果,那如果我們想對(duì)某個(gè)組件實(shí)現(xiàn)一組動(dòng)效,比如下面的效果,該怎么辦?

staggered animation

這個(gè)時(shí)候我們需要用到組合動(dòng)效, Flutter 提供了交錯(cuò)動(dòng)畫(Staggered Animation)的方式實(shí)現(xiàn)。對(duì)于多個(gè) Anmation 對(duì)象,可以共用一個(gè) AnimationController,然后在不同的時(shí)間段執(zhí)行動(dòng)畫效果。這就有點(diǎn)像 GIF 圖片一樣,一幀幀圖像播放實(shí)現(xiàn)連續(xù)的動(dòng)畫。

交錯(cuò)動(dòng)畫機(jī)制

交錯(cuò)動(dòng)畫的實(shí)現(xiàn)基于以下幾個(gè)要點(diǎn):

  • 所有的 animation對(duì)象使用同一個(gè) AnimationController 驅(qū)動(dòng);
  • 不管實(shí)際動(dòng)畫持續(xù)的時(shí)間長(zhǎng)度多長(zhǎng),動(dòng)畫控制器 controller 的值必須在0-1之間;
  • 每個(gè)動(dòng)畫對(duì)象都有一個(gè)0-1范圍內(nèi)的間隔(Interval);
  • 在間隔時(shí)間內(nèi),Tween 對(duì)象從起始值過(guò)渡到結(jié)束值。
  • 由 AnimationController 統(tǒng)一管理這些Tween 產(chǎn)生的 Animation 對(duì)象。

聽(tīng)起來(lái)有點(diǎn)抽象,我們以一張圖來(lái)表述就清晰多了,假設(shè)我們有4個(gè)動(dòng)畫對(duì)象,分別控制組件的透明度(Opacity),寬度(Width),高度(Height)和顏色(Color),交錯(cuò)動(dòng)畫過(guò)程如下:

時(shí)序示意圖

controller 是一個(gè)從0到1的歸一化的動(dòng)畫控制,其實(shí)對(duì)應(yīng)的就是動(dòng)畫時(shí)長(zhǎng)的歸一化。然后 Opacity 透明度動(dòng)效占據(jù)了0-0.25區(qū)間;Width 占據(jù)了0.25-0.5區(qū)間;Height 占據(jù)了0.5-0.75區(qū)間;最后是 Color 占據(jù)了0.75-1.0的區(qū)間。區(qū)間對(duì)應(yīng)就是動(dòng)畫的時(shí)間間隔,只是每個(gè)區(qū)間內(nèi)的Tween 動(dòng)畫對(duì)象的取值范圍都是0-1以控制從起始值到結(jié)束值。我們可以理解為是 AnimationController 將多個(gè) Animation 對(duì)象按序(也可以重合)拼接起來(lái)形成復(fù)合形式的動(dòng)畫。

代碼實(shí)現(xiàn)

看上面的說(shuō)明是不是覺(jué)得還有些難以理解,我們來(lái)一段示例代碼就很容易明白了。下面的代碼我們定義了一個(gè)共用的_controller,然后四段動(dòng)畫對(duì)象_opaticy,_width,_height 和_color。其中關(guān)鍵的實(shí)現(xiàn)是使用了 Tween 對(duì)象的 animate 方法,并指定了一個(gè) CurvedAnimation 對(duì)象作為 其parent 參數(shù)。而這個(gè)CurvedAnimation實(shí)際使用 Interval 來(lái)切分_controller 的動(dòng)畫時(shí)間,從而可以將多個(gè) Animation 對(duì)象組合起來(lái)。

import?'package:flutter/material.dart';

class?StaggeredAnimationDemo?extends?StatefulWidget?{
??StaggeredAnimationDemo({Key??key})?:?super(key:?key);

??@override
??_StaggeredAnimationDemoState?createState()?=>?_StaggeredAnimationDemoState();
}

class?_StaggeredAnimationDemoState?extends?State<StaggeredAnimationDemo>
????with?SingleTickerProviderStateMixin?{
??late?AnimationController?_controller;
??late?Animation<double>?_opacity;
??late?Animation<double>?_width;
??late?Animation<double>?_height;
??late?Animation<Color?>?_color;

??@override
??void?initState()?{
????_controller?=
????????AnimationController(duration:?Duration(seconds:?2),?vsync:?this)
??????????..addListener(()?{
????????????setState(()?{});
??????????});
????_opacity?=?Tween<double>(begin:?0.5,?end:?1.0).animate(
??????CurvedAnimation(
????????parent:?_controller,
????????curve:?Interval(
??????????0.0,
??????????0.25,
??????????curve:?Curves.easeIn,
????????),
??????),
????);
????_width?=?Tween<double>(begin:?0.0,?end:?2.0).animate(
??????CurvedAnimation(
????????parent:?_controller,
????????curve:?Interval(
??????????0.25,
??????????0.5,
??????????curve:?Curves.easeIn,
????????),
??????),
????);
????_height?=?Tween<double>(begin:?0.0,?end:?2.0).animate(
??????CurvedAnimation(
????????parent:?_controller,
????????curve:?Interval(
??????????0.5,
??????????0.75,
??????????curve:?Curves.easeIn,
????????),
??????),
????);
????_color?=?ColorTween(begin:?Colors.green,?end:?Colors.blue).animate(
??????CurvedAnimation(
????????parent:?_controller,
????????curve:?Interval(
??????????0.75,
??????????1.0,
??????????curve:?Curves.easeIn,
????????),
??????),
????);
????super.initState();
??}

??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
??????appBar:?AppBar(
????????title:?const?Text('交錯(cuò)動(dòng)畫'),
??????),
??????body:?Center(
????????child:?Opacity(
??????????opacity:?_opacity.value,
??????????child:?Container(
????????????width:?100?+?100?*?_width.value,
????????????height:?100?+?100?*?_height.value,
????????????color:?_color.value,
??????????),
????????),
??????),
??????floatingActionButton:?FloatingActionButton(
????????child:?Icon(Icons.play_arrow),
????????onPressed:?()?{
??????????if?(_controller.isCompleted)?{
??????????????_controller.reverse();
????????????}?else?if?(!_controller.isAnimating)?{
??????????????_controller.forward();
??????????}
????????},
??????),
????);
??}
}

我們來(lái)看一下運(yùn)行效果,可以看到運(yùn)行的動(dòng)畫過(guò)程其實(shí)就是4段動(dòng)畫效果拼接來(lái)的,先是透明度改變,然后是寬度改變,再之后是高度改變,最后是顏色的改變。

運(yùn)行效果

Interval 介紹

我們來(lái)看一下關(guān)鍵的 Interval 類的介紹。

A curve that is 0.0 until [begin], then curved (according to [curve]) from 0.0 at [begin] to 1.0 at [end], then remains 1.0 past [end].

Interval 類繼承自 Curve,所不同的是,在 begin 之前曲線的值一直保持為0.0,而在 end 之后一直保持為1.0。所以可以理解為,在 AnimationController 啟動(dòng)動(dòng)畫后,Interval 曲線其實(shí)也已經(jīng)在繪制,只是有效的取值區(qū)間只在 begin 到 end 之間,下面就是 Interval 的一種示例曲線圖。

image.png

從 Interval 的源碼也能看出來(lái),其中 clamp 方法限制了取值范圍,當(dāng) t <= begin 的時(shí)候取值就是0,當(dāng) t >= end的時(shí)候,取值就是1.0。

@override
double?transformInternal(double?t)?{
??assert(begin?>=?0.0);
??assert(begin?<=?1.0);
??assert(end?>=?0.0);
??assert(end?<=?1.0);
??assert(end?>=?begin);
??t?=?((t?-?begin)?/?(end?-?begin)).clamp(0.0,?1.0);
??if?(t?==?0.0?||?t?==?1.0)
????return?t;
??return?curve.transform(t);
}

總結(jié)

本篇介紹了交錯(cuò)動(dòng)畫的實(shí)現(xiàn)機(jī)制和示例,通過(guò)交錯(cuò)動(dòng)畫給了我們更多動(dòng)效組合的空間,從而可以實(shí)現(xiàn)類似 GIF圖片的那種多幀組合在一起的動(dòng)畫效果。

到此這篇關(guān)于Android Flutter實(shí)現(xiàn)GIF動(dòng)畫效果的方法詳解的文章就介紹到這了,更多相關(guān)Android Flutter GIF動(dòng)畫效果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android EditText限制輸入整數(shù)和小數(shù)的位數(shù)的方法示例

    Android EditText限制輸入整數(shù)和小數(shù)的位數(shù)的方法示例

    這篇文章主要介紹了Android EditText限制輸入整數(shù)和小數(shù)的位數(shù)的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Android實(shí)現(xiàn)可拖拽帶有坐標(biāo)尺進(jìn)度條的示例代碼

    Android實(shí)現(xiàn)可拖拽帶有坐標(biāo)尺進(jìn)度條的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用Android實(shí)現(xiàn)可拖拽帶有坐標(biāo)尺進(jìn)度條的效果,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下
    2023-06-06
  • Anroid四大組件service之本地服務(wù)的示例代碼

    Anroid四大組件service之本地服務(wù)的示例代碼

    本篇文章主要介紹了Anroid四大組件service之本地服務(wù)的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • Android文字基線Baseline算法的使用講解

    Android文字基線Baseline算法的使用講解

    今天小編就為大家分享一篇關(guān)于Android文字基線Baseline算法的使用講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • Android開(kāi)發(fā)之圖形圖像與動(dòng)畫(四)AnimationListener簡(jiǎn)介

    Android開(kāi)發(fā)之圖形圖像與動(dòng)畫(四)AnimationListener簡(jiǎn)介

    就像Button控件有監(jiān)聽(tīng)器一樣,動(dòng)畫效果也有監(jiān)聽(tīng)器,只需要實(shí)現(xiàn)AnimationListener就可以實(shí)現(xiàn)對(duì)動(dòng)畫效果的監(jiān)聽(tīng),感興趣的朋友可以了解下啊,希望本文對(duì)你有所幫助
    2013-01-01
  • Android 的Bitmap的修改方法

    Android 的Bitmap的修改方法

    Android 的Bitmap的修改方法,需要的朋友可以參考一下
    2013-05-05
  • Android利用Intent實(shí)現(xiàn)記事本功能(NotePad)

    Android利用Intent實(shí)現(xiàn)記事本功能(NotePad)

    這篇文章主要為大家詳細(xì)介紹了Android利用Intent實(shí)現(xiàn)簡(jiǎn)單記事本功能(NotePad)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Android開(kāi)發(fā)技巧之ViewStub控件惰性裝載

    Android開(kāi)發(fā)技巧之ViewStub控件惰性裝載

    布局文件中的控件并不一定在程序啟動(dòng)時(shí)全都用到,有一些控件只在特定的情況下才會(huì)被使用到;我們急需一種機(jī)制來(lái)改變<include>標(biāo)簽的這種行為,只在需要時(shí)裝載控件。這種機(jī)制就是本節(jié)要介紹的ViewStub控件
    2013-01-01
  • Android如何給Textview添加菜單項(xiàng)詳解(Java)

    Android如何給Textview添加菜單項(xiàng)詳解(Java)

    TextView是android里面用的最多的控件,TextView類似一般UI中的Label,TextBlock等控件,只是為了單純的顯示一行或多行文本,下面這篇文章主要給大家介紹了關(guān)于Android如何給Textview添加菜單項(xiàng)的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • android自定義帶箭頭對(duì)話框

    android自定義帶箭頭對(duì)話框

    這篇文章主要為大家詳細(xì)介紹了android自定義帶箭頭對(duì)話框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03

最新評(píng)論