如何在Flutter中显示动画图片?

时间:2017-10-02 03:50:46

标签: dart flutter

我希望在Flutter中显示动画图片,无论其格式如何。事实是,目前似乎只有一种解决方案,video_loader。这仅适用于全屏,但不适合我的用例。

关于我如何解决这个问题的任何想法?

4 个答案:

答案 0 :(得分:21)

现在,图像小部件支持GIF。 (4月18日)

对于前。

new Image(image: new AssetImage("assets/ajax-loader.gif"))

答案 1 :(得分:14)

您可以使用https://ezgif.com/split将帧拆分为单独的图像,并将它们作为资源添加到pubspec.yaml中。

然后使用Animation<int>选择要显示的正确帧。请务必设置gaplessPlayback: true以避免闪烁。

例如,以下代码显示由Guillaume Kurkdjian创建的animated GIF的帧。

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      theme: new ThemeData.dark(),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  AnimationController _controller;
  Animation<int> _animation;

  @override
  void initState() {
    _controller = new AnimationController(vsync: this, duration: const Duration(seconds: 5))
      ..repeat();
    _animation = new IntTween(begin: 0, end: 116).animate(_controller);
  }

  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          new AnimatedBuilder(
            animation: _animation,
            builder: (BuildContext context, Widget child) {
              String frame = _animation.value.toString().padLeft(3, '0');
              return new Image.asset(
                'assets/frame_${frame}_delay-0.04s.png',
                gaplessPlayback: true,
              );
            },
          ),
          new Text('Image: Guillaume Kurkdjian', style: new TextStyle(fontStyle: FontStyle.italic)),
        ],
      ),
    );
  }
}

答案 2 :(得分:2)

2021 年更新

截至目前,flutter 确实支持使用 gif 小部件播放 Image 文件。

Image.asset('assets/logo.gif')

但是当前在 flutter 中加载 gif 的方式存在问题。 gif 循环播放,播放一次后您无法停止 gif。还有其他使用 Rive 和 Lottie 显示动画图片的方法,它们都带有维护良好的 flutter 包,提供了许多开箱即用的功能。

解决方法:

  1. 将您的 gif 转换为 mp4 (Gif to mp4)
  2. 将 mp4 转换为 Lottie json (Mp4 to Json)
  3. 将您的 Lottie json 上传到 lottiefiles.com 或添加到您的 assets 文件夹
  4. 使用 Lottie package 加载动画

来自 Lottie package 文档的示例:

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ListView(
          children: [
            // Load a Lottie file from your assets
            Lottie.asset('assets/LottieLogo1.json'),

            // Load a Lottie file from a remote url
            Lottie.network(
                'https://raw.githubusercontent.com/xvrh/lottie-flutter/master/example/assets/Mobilo/A.json'),

            // Load an animation and its images from a zip file
            Lottie.asset('assets/lottiefiles/angel.zip'),
          ],
        ),
      ),
    );
  }
}

当然,这不是加载 gif 的最理想方式,因为这只是一种解决方法。如果您不怎么使用 Image,您可以简单地使用 gif 小部件。但是,如果您将使用 Lottie,那么您可以通过更多控制权使用 gif 执行许多操作。

答案 3 :(得分:0)

为了只运行gif动画一次,有2种解决方案。

第一个解决方案。

List<int> listGifDuration = [0,0,22,26,31,27,30,29,29,23,29,24,25,27,33,33,29,29];
List<int> listGifDurationDs = [0,0,1,0,0,0,0,0,0,0,0,0,0,0,5,2,5,0];
List<double> listGifFrames = [0,0,315,389,310,294,435,423,425,331,425,360,365,395,309,384,426,435];
strgif = "assets/gif/motion-all.gif"
fetchGif(AssetImage(strgif)).then((value)  {
 controller= GifController(vsync: this,duration: Duration(seconds: listGifDuration[widget.storyid]));
 controller.addListener(() => setState(() {}));
 TickerFuture tickerFuture = controller.repeat(min:0,max:listGifFrames[widget.storyid],period:Duration(seconds: listGifDuration[widget.storyid]));
              tickerFuture.timeout(Duration(seconds: listGifDuration[widget.storyid]), onTimeout:  () {
                controller.forward(from: 0);
                controller.stop(canceled: true);
              });
        });

第二个解决方案。

将gif文件的属性从无限循环转换为1个循环。

请使用以下链接转换gif文件的循环计数。

https://ezgif.com/loop-count

然后

child: new Image.asset(strgif),