こんにちは。株式会社Pentagonでアプリ開発をしているmamiです。
今回はFlutterでサーバへのリクエスト中など処理に時間がかかる時に、画面にローディングアニメーションを表示する方法について調べました。よく使われているのは、「CircularProgressIndicator」というウィジェットでくるくる回るインディケーターが表示されます。今回はくるくるインジケーターの部分を好きなアニメーションに変えて表示させる方法についてご紹介します。
【こんな人に読んで欲しい】
- ユーザーエクスペリエンス(UX)を向上させたい方
- ユーザーを飽きさせず、離脱を防ぎたい方
- ユーザーの処理待ちに伴うストレスや不安を軽減させたい方
【この記事を読むメリット】
手軽にアプリにアニメーションを導入することが出来ます。
【結論】
LottieやRiveなどのアニメーションフレームワークを使用すると、手軽にローディングアニメーションを取り入れることが出来ます。
アニメーション実装方法の選択
Flutter でアニメーションを作成するときは、さまざまな方法があります。どのようなアニメーションを表示したいかで、選択するものが変わってきます。
Flutter公式ページでディシジョンツリー(Decision Tree)が用意されているので、それを元に選択すると良いと思います。公式ページは英語で記載されているので、翻訳したものを掲載します。
引用:https://docs.flutter.dev/development/ui/animations
以下のように分類することができます。
アニメーションフレームワーク(LottieやRive(旧Flare)など) | |
CustomPainter | |
Implicit animations(暗黙的) | AnimatedDefaultTextStyle |
TweenAnimationBuilder | |
AnimatedFoo | |
Explicit Animation(明示的) | FooTransition |
AnimatedBuilder | |
AnimationWidget |
アニメーションフレームワーク(LottieやRiveなど)
アニメーションフレームワーク(LottieやRiveなど)は、作成したいものがコードで行うのが難しい場合やアニメーションにSVG・ベクターの使用が含まれる場合に使用します。
CustomPainter
CustomPaintウィジェットを使用して、キャンバス上に様々な図形(線、円、四角形など)を描画をすることができます。
Implicit Animations(暗黙的なアニメーション)とExplicit Animation(明示的なアニメーション)
Implicit Animations(暗黙的なアニメーション)とExplicit Animation(明示的なアニメーション)は、ウィジェットのサイズ、スケール、位置などを変更することができます。例えば、ショッピングリストの商品の写真をカートのアイコンに移動させることができます。
Implicit Animations(暗黙的なアニメーション)には、簡単に使用出来るモーションアニメーションが用意されています。これらのタイプのアニメーションは、Implicit Animations(暗黙的なアニメーション)と呼ばれます。
アニメーションをより細かく制御したい場合は、明示的なアニメーションを使用する必要があります。曲線、期間(開始と終了)、およびトリガーの種類を指定して明示的に定義する必要があるアニメーションは、Explicit Animation(明示的なアニメーション)と呼ばれます。
ローディング向きアニメーションは?
CustomPainterやImplicit Animations(暗黙的なアニメーション)、Explicit Animation(明示的なアニメーション)は、ローディングアニメーションをするにはコード量が多くなり、簡単には作れません。LottieやRiveなどのアプリケーションフレームワークを使うことをお勧めします。
Lottie(ロッティ)とは
Lottieは、AdobeのAfter Effectsで作成したアニメーションをJSON形式(LottieFiles)にエクスポートするフレームワークです。LottieFilesはSVG と同様にベクター形式であるため、アニメーション化されたアイコンがどんなに小さくても大きくても、品質が低下することはありません。GIFより小さく、ほぼすべてのプラットフォーム(Mac、iOS、Android、Windowsの一部)に対応しています。問題は、AdobeのAfter Effectsをある程度使いこなせる人が必要になります。また、After Effectsの全機能は使えず、使用できるアニメーションには限りがあります。シンプルなアニメーションにする場合は、 Lottieを使用するのが最適です。
Rive(ライブ)とは
一方、アニメーションに重点を置き、より詳細な制御が必要な場合はRive(旧Flare)がお勧めです。Lottie よりも高速で、サイズが小さく、消費するメモリも少なくて済みます。またAfter Effects などの他社ツールを使用せず独自のRiveエディタを使うことができます。ただし、After Effectsの方が機能が多く、使いやすいです。
Lottie・Riveの実装方法
インターネット上にあるLottieファイル(拡張子json)、Riveファイル(拡張子riv)を使用して、どのように動かすのかを確認します。
Step0. main.dart等にLottie,Riveそれぞれの呼び出しボタンを作成
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("アニメーション"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
child: const Text('Lottie Loading'),
onPressed: () {
_showLottieLoading();
},
ElevatedButton(
child: const Text('Rive Loading'),
onPressed: () {
_showRiveLoading();
},
),
],
),
),
);
}
Lottie実装方法
Step1. pubspec.yaml に次の行を追加します。 (そして flutter pub get を実行します)
dependencies:
lottie: ^2.1.0
Step2. main.dart等にimport文を追加
import 'package:lottie/lottie.dart';
Step3. main.dart等にコード記載
呼び出しボタン押下時のアニメーション表示部分を作成します。
_showLottieLoading() {
showGeneralDialog(
context: context,
barrierDismissible: false,
transitionDuration: Duration(milliseconds: 250),
barrierColor: Colors.black.withOpacity(0.5),
pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white,
child: Column(
mainAxisAlignment:MainAxisAlignment.center,
crossAxisAlignment:CrossAxisAlignment.center,
children: [
Lottie.network(
'https://assets10.lottiefiles.com/packages/lf20_07PkRX.json'),
ElevatedButton(
child: const Text('LoadingOff'),
onPressed: () {
Navigator.pop(context);
},
)
],
),
);
}
);
Rive実装方法
Step1. pubspec.yaml に次の行を追加します。 (そして flutter pub get を実行します)
dependencies:
rive: ^0.10.0
Step2. pubspec.yaml にAssetsを追加しRivファイルを格納
assets:
- assets/
サンプル用のRivファイルはRiveホームページのコミュニティよりダウンロードしたものを上記assetsフォルダに格納します。
Step3. main.dart等にimport文を追加
import 'package:rive/rive.dart';
Step4. main.dart等にコード記載
呼び出しボタン押下時のアニメーション表示部分を作成します。
"Sway Loading animation" by niek1 is licensed under CC BY 4.0
_showRiveLoading() {
showGeneralDialog(
context: context,
barrierDismissible: false,
transitionDuration: Duration(milliseconds: 250),
barrierColor: Colors.black.withOpacity(0.5),
pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white,
child: Column(
mainAxisAlignment:MainAxisAlignment.center,
crossAxisAlignment:CrossAxisAlignment.center,
children: [
SizedBox(
height: 300,
child: RiveAnimation.asset('assets/loading.riv'),
),
ElevatedButton(
child: const Text('LoadingOff'),
onPressed: () {
Navigator.pop(context);
},
)
],
),
);
}
);
}
Lottie・Riveを使用する上での制限事項
Lottie、Riveは無料で始めることが出来ますが、無料枠には制限があります。価格については各公式ホームページをご確認ください。また、インターネット上にあるLottieファイル、Riveファイルを使用する場合はライセンスをご確認の上、使用してください。
Lottie、Riveを使用することが難しい場合、サイズや解像度に問題なければ上記のLottieファイル、Riveファイルの呼び出し部分を以下のようにGIF表示にしてもローディングアニメーションとして使用出来ます。
Image.asset("assets/loading.gif"),
まとめ
LottieやRiveを使用すると複雑なアニメーションを少ないコード量で表示することが出来ます。しかもLottieファイル、RiveファイルともにGIFよりサイズも小さく(両方とも10KB以下)、綺麗に表示することが出来ました。ローティング中にちょっとしたアニメーションを取り入れたい方は是非使ってみてください。