【Flutter】FlutterでLottie動かしてみた ~Flutter製アプリをおしゃれに！！~




# 目次
[1.はじめに](#はじめに)
[2.サンプル](#サンプル)
[3.使用パッケージ](#使用パッケージ)
[4.実装](#実装)
[4-(1)１回だけ動くLottie](#1回だけ動くlottie)
[4-(2)【応用】PageViewを使用してスライドショーのように使うLottie](#応用pageviewを使用してスライドショーのようにlottieを使用)
[5.まとめ](#まとめ)
# はじめに
Lottieとは、jsonベースのアニメーションファイルです。
簡単に説明しますと、gif画像より軽く、高品質なアニメーションと思っていただけると良いかと思います！
そんなLottieは公式サイトから簡単に素材をダウンロードできますのでお試しください！
それでは早速FlutterでLottieアニメーションを動かしてみましょう！

https://lottiefiles.com/

Lottie公式サイト
# サンプル
こちらはシミュレーターを画面録画したGIF画像になりますので、実際にはもっとぬるぬるです！
![20230903_231926.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3075676/b7df91ea-a2f5-06c2-84b9-c19972203db0.gif)

# 使用パッケージ

使用するパッケージ
* [lottie](https://pub.dev/packages/lottie)

そのままでわかりやすいですね。

https://pub.dev/packages/lottie

# 実装
コードを書いていきましょう！

1. プロジェクトファイルにassetsにフォルダを作成してダウンロードしたLottieファイル(.json)を配置(URLから呼び出す場合は必要ない)

2. pubspec.yamlのassets設定
```pubspec.yaml
assets:
    - assets/名前.json
```



3.FlutterでAssetsからLottieを呼び出す

### 1回だけ動くLottie
これは公式のUsageにあるものを少しアレンジしたWidgetです。
一回だけ再生されて下のボタンを押すともう一度最初から再生できるものとなっております。

Lottieは基本的にStatefulWidgetをTickerProviderStateMixinで拡張AnimationControllerでコントロールします。


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

class SingleShotLottie extends StatefulWidget {
  SingleShotLottie({super.key, required this.asset});
  final String asset;

  @override
  State<SingleShotLottie> createState() => _SingleShotLottieState();
}

class _SingleShotLottieState extends State<SingleShotLottie>
    with TickerProviderStateMixin {
  late final AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
  }

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          width: 200,
          height: 200,
          child: Lottie.asset(
            widget.asset,//ここでassetsのパスを直接入力しても良い
            controller: _controller,
            onLoaded: (composition) {
              _controller
                ..duration = composition.duration
                ..forward().then((value) => _controller.reset());
            },
          ),
        ),
        ElevatedButton(
            onPressed: () {
              setState(() {
                _controller.forward().then((value) => _controller.reset());
              });
            },
            child: const Text('もう一度みる'))
      ],
    );
  }
}
```
* AnimationControllerのメソッド
forward() =>　再生
reset() => 最初に戻る


おそらくこんな感じだと思う




### 【応用】PageViewを使用してスライドショーのようにLottieを使用
PageViewを横にスライドしたタイミングでLottieが再生されるWidgetです。
初回起動時のチュートリアルなんかに使用するとそれっぽく見えていい感じになるかなと思います。


```slide_show_lottie.dart

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

final list = ['assets/1.json','assets/2.json','assets/3.json','assets/4.json','assets/5.json','assets/6.json'];//スライドショーに使用したいLottieのassetsパスのリスト


class SlideShowlottie extends StatefulWidget {
  const SlideShowlottie(
      {super.key,
      required this.assetsList,
      this.width = 300,
      this.height = 300,
      this.isBorder = false});

  ///スライドショーのassetのリスト
  final List assetsList;

  ///スライドショーの幅(デフォルト300)
  final double width;

  ///スライドショーの高さ(デフォルト300)
  final double height;

  ///スライドショーの範囲の枠を表示するかしないか(デフォルトでは表示しない)
  final bool isBorder;

  @override
  _SlideShowlottieState createState() => _SlideShowlottieState();
}

class _SlideShowlottieState extends State<SlideShowlottie>
    with TickerProviderStateMixin {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    var controllre = AnimationController(
        vsync: this,

        //Durationの値で再生から終了までにかかる時間を設定できる。指定なしであれば元々のファイルの再生時間で再生
        duration: Duration(seconds: 5));

    void startAnimation() {
      if (controllre.value == 0) {
        controllre.forward().then((value) => controllre.reset());
      }
      if (controllre.value != 0) {
        controllre.reset();
        controllre.forward();
      }
    }

    void stopAnimation() {
      controllre.stop();
    }

    var pageController = PageController();

    _onChanged(int page) {
      startAnimation();
    }

    startAnimation();
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Container(
            width: widget.width,
            height: widget.height,
            decoration: BoxDecoration(
              border: widget.isBorder ? Border.all(color: Colors.black) : null,
            ),
            child: PageView.builder(
                itemCount: widget.assetsList.length,
                controller: pageController,
                onPageChanged: _onChanged,
                itemBuilder: (context, i) {
                  return LottieTile(
                      animationController: controllre,
                      assets: widget.assetsList[i]);
                })),
        ElevatedButton(
          child: const Text('もう一度見る'),
          onPressed: () {
            startAnimation();
          },
        ),
      ],
    );
  }
}

///スライドショーの中に入るタイル
class LottieTile extends StatelessWidget {
  const LottieTile(
      {super.key, required this.animationController, required this.assets});
  final AnimationController animationController;
  final String assets;
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Lottie.asset(assets, controller: animationController),
    );
  }
}
```
# まとめ
AnimationControllerを使ったことなくてもなんとなくコピペだけでも動くので比較的簡単に実装できました。

LottieをFlutterで動かすのはそんなに難しくないので、ぜひアプリをワンランク上のものに見せたい時に使用してみてください！

ソースコードはgitにありますので参考にしてみてください！

https://github.com/sodateya/lottie_sample