くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

FlutterでLottieをつかう&終了を検知する

FlutterでもLottieを使いたいなと思い、
いろいろ調べたときの備忘録(*´ω`*)

できたのはこんな感じ

使い方

使い方はこんな感じ。表示だけならこれだけでOK

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

class SimpleLottie extends HookConsumerWidget {
  const SimpleLottie({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Lottie.asset('assets/LottieLogo1.json');
  }
}

終了を検知する

アニメーションの開始、終了をriverpodで扱いたいなと思い、
こんな感じにしたら、よい感じになった

// 表示/非表示のフラグ用のProvider
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'lottie_provider.g.dart';

@Riverpod(keepAlive: true)
class Lottie extends _$Lottie {
  @override
  bool build() => false;
  void play() => state = true;
  void stop() => state = false;
}

アニメーションを含むWidgetはこんな感じ。
AnimationControlleraddStatusListenerで、
終了状態を監視する。

// 手動でコントロールするWidget
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:lottie/lottie.dart';

class ManualLottie extends HookConsumerWidget {
  const ManualLottie({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // AnimationControllerを用意
    final controller = useAnimationController();
    
    // statusをlistenして、終了したらflagをOFFにする
    controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        ref.read(lottieProvider.notifier).stop();
      }
    });
    
    // widget自体のdispose時にflagをOFFにする
    useEffect(() {
      return () => ref.read(lottieProvider.notifier).stop();
    }, const []);
    
    return Lottie.asset(
      'assets/LottieLogo1.json',
      repeat: false,
      controller: controller,
      onLoaded: (composition) {
        // 読み込み完了時にdurationを設定
        controller.duration = composition.duration;
        // アニメーションを開始
        controller.forward();
      },
    );
  }
}

あとは、好きな場所で、lottieProviderとあわせて指定し、
ref.watch(lottieProvider.notifier).play()を呼べばOK

class ShowLottie extends HookConsumerWidget {
  const ShowLottie({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final isShow = ref.watch(lottieProvider);
    
    return const Column(
      children: [
        if (isShow) ManualLottie(),
      ],
    );
  }
}

以上!! これでいい感じになった気がする(*´ω`*)

maguro-sagashi.com

参考にしたサイト様