💅

Flutter×Lottie Flutterアプリをワンランクおしゃれにしよう!

2023/09/14に公開

目次

1.はじめに
2.サンプル
3.使用パッケージ
4.実装
4-(1)1回だけ動くLottie
4-(2)【応用】PageViewを使用してスライドショーのように使うLottie
5.まとめ

はじめに

Lottieとは、jsonベースのアニメーションファイルです。
簡単に説明しますと、gif画像より軽く、高品質なアニメーションと思っていただけると良いかと思います!
そんなLottieは公式サイトから簡単に素材をダウンロードできますのでお試しください!
それでは早速FlutterでLottieアニメーションを動かしてみましょう!

https://lottiefiles.com/

Lottie公式サイト

サンプル

こちらはシミュレーターを画面録画したGIF画像になりますので、実際にはもっとぬるぬるです!
20230903_231926.GIF

使用パッケージ

使用するパッケージ

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

https://pub.dev/packages/lottie

実装

コードを書いていきましょう!

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

  2. pubspec.yamlのassets設定

assets:
    - assets/名前.json

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

1回だけ動くLottie

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

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

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です。
初回起動時のチュートリアルなんかに使用するとそれっぽく見えていい感じになるかなと思います。


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

Flutter大学

Discussion