Flutter開(kāi)發(fā)之幀動(dòng)畫(huà)

最近寫(xiě)了一些flutter的小動(dòng)畫(huà),在這里也寫(xiě)幾個(gè)篇章介紹下flutter的動(dòng)畫(huà)的實(shí)現(xiàn)备徐,先實(shí)現(xiàn)個(gè)簡(jiǎn)單的幀動(dòng)畫(huà)淮阐,舉例美團(tuán)的加載動(dòng)畫(huà)就是幀動(dòng)畫(huà)的實(shí)現(xiàn),那換flutter的怎么實(shí)現(xiàn)呢望侈,一起看看

主要的類實(shí)現(xiàn)FrameAnimationImage



class FrameAnimationImage extends StatefulWidget {
  final List<String> _assetList;
  final double width;
  final double height;
  bool start = true;
  int interval = 200;

  FrameAnimationImage(Key key, this._assetList,
      {this.width, this.height, this.interval, this.start})
      : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return FrameAnimationImageState();
  }
}

class FrameAnimationImageState extends State<FrameAnimationImage>
    with SingleTickerProviderStateMixin {
  // 動(dòng)畫(huà)控制
  Animation<double> _animation;
  AnimationController _controller;
  int interval = 200;

  @override
  void initState() {
    super.initState();

    if (widget.interval != null) {
      interval = widget.interval;
    }
    final int imageCount = widget._assetList.length;
    final int maxTime = interval * imageCount;

    // 啟動(dòng)動(dòng)畫(huà)controller
    _controller = new AnimationController(
        duration: Duration(milliseconds: maxTime), vsync: this);
    _controller.addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed) {
        _controller.forward(from: 0.0); // 完成后重新開(kāi)始
      }
    });

    _animation = new Tween<double>(begin: 0, end: imageCount.toDouble())
        .animate(_controller)
      ..addListener(() {
        setState(() {
          // the state that has changed here is the animation object’s value
        });
      });
    if (widget.start) {
      _controller.forward();
    }
  }

  void startAnimation() => _controller.forward();
  void stopAnimation() => _controller.stop();
  void reStartAnimation(){
    _controller.reset();
    _controller.forward();
  }

  @override
  void didUpdateWidget(FrameAnimationImage oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget called");
    if (widget.start) {
      _controller.forward();
    }
  }

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

  @override
  Widget build(BuildContext context) {
    int ix = _animation.value.floor() % widget._assetList.length;

    List<Widget> images = [];
    // 把所有圖片都加載進(jìn)內(nèi)容,否則每一幀加載時(shí)會(huì)卡頓
    for (int i = 0; i < widget._assetList.length; ++i) {
      if (i != ix) {
        images.add(Image.asset(
          ImageUtils.getImagePath( widget._assetList[i]),///ImageUtils只是一個(gè)簡(jiǎn)單出來(lái)圖片格式的方法
          width: 0,
          height: 0,
        ));
      }
    }

    images.add(Image.asset(
      ImageUtils.getImagePath(widget._assetList[ix]),//

      width: widget.width,
      height: widget.height,
    ));

    return Stack(alignment: AlignmentDirectional.center, children: images);
  }
}
//class ImageUtils {
//  static String getImagePath(String name, {String format: 'png'}) {
//    return 'assets/images/$name.$format';
//  }
//
//  static ImageProvider getImageProvider(String imageUrl,
//      {String holderImg: "none"}) {
//    if (TextUtil.isEmpty(imageUrl)) {
//      return AssetImage(getImagePath(holderImg));
//    }
//    return CachedNetworkImageProvider(imageUrl);
//  }
//} 

這個(gè)類的實(shí)現(xiàn)也比較好理解的勋桶,通過(guò)監(jiān)聽(tīng)AnimationStatus 動(dòng)畫(huà)的狀態(tài)脱衙,對(duì)動(dòng)畫(huà)實(shí)現(xiàn)控制。下面看下實(shí)現(xiàn)示例.
準(zhǔn)備好圖片:

go1.png
go2.png
go3.png
go4.png

class Frame extends StatelessWidget {

  bool b = false;
 
  final List<String> list = [
    'go1',
    'go2',
    'go3',
    'go4',

  ];
  final GlobalKey<FrameAnimationImageState> _cotroller = new GlobalKey<FrameAnimationImageState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('幀動(dòng)畫(huà)'),
          centerTitle: true,
        ),
        body: Column(
          children: <Widget>[
            Center(
              child: GestureDetector(
                onTap: () {
                  if (b) {
                    _cotroller.currentState.reStartAnimation();
                  } else {
                    _cotroller.currentState.startAnimation();

                  }

                  b = !b;
                },
                child: FrameAnimationImage(_cotroller, list,
                    width: 220, height: 200, interval: 50, start: false),
              ),
            ),
            RaisedButton(
              onPressed: (){
                _cotroller.currentState.stopAnimation();
              },
              child: Text("結(jié)束"),
            )
          ],
        )

 );
  }

}

將圖片上去例驹,運(yùn)行捐韩、就可以看見(jiàn)小鹿跑動(dòng)的動(dòng)畫(huà)啦。
很簡(jiǎn)單是不是鹃锈,幀動(dòng)畫(huà)就這樣吧荤胁,要是控制時(shí)間什么的自己添加修改就好了,還有注意幀動(dòng)畫(huà)圖片的大小喔屎债。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仅政,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子盆驹,更是在濱河造成了極大的恐慌圆丹,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件躯喇,死亡現(xiàn)場(chǎng)離奇詭異辫封,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)廉丽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)倦微,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人正压,你說(shuō)我怎么就攤上這事欣福。” “怎么了蔑匣?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵劣欢,是天一觀的道長(zhǎng)棕诵。 經(jīng)常有香客問(wèn)我裁良,道長(zhǎng)凿将,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任价脾,我火速辦了婚禮牧抵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侨把。我一直安慰自己犀变,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布秋柄。 她就那樣靜靜地躺著获枝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪骇笔。 梳的紋絲不亂的頭發(fā)上省店,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音笨触,去河邊找鬼懦傍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛芦劣,可吹牛的內(nèi)容都是我干的粗俱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼虚吟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寸认!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起串慰,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤废麻,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后模庐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體烛愧,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年掂碱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了怜姿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疼燥,死狀恐怖沧卢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情醉者,我是刑警寧澤但狭,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布披诗,位于F島的核電站,受9級(jí)特大地震影響立磁,放射性物質(zhì)發(fā)生泄漏呈队。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一唱歧、第九天 我趴在偏房一處隱蔽的房頂上張望宪摧。 院中可真熱鬧,春花似錦颅崩、人聲如沸几于。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)沿彭。三九已至,卻和暖如春尖滚,著一層夾襖步出監(jiān)牢的瞬間喉刘,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工熔掺, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饱搏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓置逻,卻偏偏與公主長(zhǎng)得像推沸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子券坞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354