How to play and control gif with CachedNetworkImage in Flutter?

Viewed 768

I'm currently developing an app for deaf people and I need to use many gifs inside my app. I don't want my gifs to play more than once so I used GifImage which lets me control the number of reproductions and the speed of the gif locally.

Now I realize that with so many gifs, my app will be too heavy to upload to the stores, so I tried using CachedNetworkImage to play my gifs from firebase storage. The problem with this library is that I have no control on the reproduction of the gifs, they play infinitely.

What I have already tried:

  1. Play gif from local file:
GifImage(
                controller: controller,
                image: AssetImage('test.gif'),
              )
  1. Play gif using CachedNetworkImage:
CachedNetworkImage(
              imageUrl:
                  'https://firebasestorage.googleapis.com/v0/b/app-lsc-7310d.appspot.com/o/test.gif?alt=media',
              fit: BoxFit.cover,
              width: MediaQuery.of(context).size.width * 0.5,
              placeholder: (context, url) => CircularProgressIndicator(),
              errorWidget: (context, url, error) => Icon(Icons.error),
            ),

I want to know if it is possible to use both libraries together so I can store the gifs in the cache and also have control over them, like so:

CachedNetworkImage(
          imageUrl:
              'https://firebasestorage.googleapis.com/v0/b/app-lsc-7310d.appspot.com/o/test.gif?alt=media',
          imageBuilder: (context, imageProvider) => GifImage(
            controller: controller,
            image: imageProvider,
          ),
          placeholder: (context, url) => CircularProgressIndicator(),
          errorWidget: (context, url, error) => Icon(Icons.error),
        ),

But I get the following error:

[VERBOSE-2:shell.cc(242)] Dart Unhandled Exception: NoSuchMethodError: The getter 'buffer' was called on null.
Receiver: null
Tried calling: buffer, stack trace: #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1      fetchGif (package:flutter_gifimage/flutter_gifimage.dart:243:76)
#2      GifImageState.didChangeDependencies (package:flutter_gifimage/flutter_gifimage.dart:158:7)
#3      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4653:11)
#4      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4469:5)
#5      Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#6      Element.updateChild (package:flutter/src/widgets/framework.dart:3303:20)
#7      SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5981:14)
#8      Element.updateChild (package:flutter/src/widgets/framework.dart:3293:15)
#9      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4520:16)
#10<…>

Here is the full code in case you want to try it out:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  GifController controller;
  String currentGif = 'test';
  double frameNum = 25.0;

  void initState() {
    controller = GifController(vsync: this);
    super.initState();
  }

  playGif(String gifToPlay) async {
    controller.value = 0;
    controller.animateTo(frameNum - 1,
        duration: Duration(milliseconds: (160 * (frameNum - 1)).toInt()));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Giphy'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CachedNetworkImage(
              imageUrl:
                  'https://firebasestorage.googleapis.com/v0/b/app-lsc-7310d.appspot.com/o/test.gif?alt=media',
              fit: BoxFit.cover,
              width: MediaQuery.of(context).size.width * 0.5,
              placeholder: (context, url) => CircularProgressIndicator(),
              errorWidget: (context, url, error) => Icon(Icons.error),
            ),
            SizedBox(
              height: 20.0,
            ),
            Card(
              child: GifImage(
                controller: controller,
                image: AssetImage('images/test.gif'),
              ),
              elevation: 7,
            ),
            SizedBox(
              height: 20.0,
            ),
            GestureDetector(
              onTap: () {
                playGif(currentGif);
              },
              child: Container(
                color: Colors.blueGrey,
                padding: EdgeInsets.all(5.0),
                child: Text(
                  'Play Local Gif',
                  style: TextStyle(fontSize: 20),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

I am open to other suggestions as well and would be really grateful for your help.

0 Answers
Related