🎃
Flutterで画像読み込み中の表示をイイ感じにしよう!
この記事を読んでほしい人
FLutterの画像読み込みで「くるくる🌀」させてる人
やること
- cached_network_imageで画像をキャッシュして表示する
- skelton_textで画像読み込み時にキラッ✨とさせる
- (おまけ)lottieでイイ感じのアニメーションをつける
これらのパッケージはインストールしておいてください!
動作イメージ
ZennのRss Feedを取得して表示しています(アニメーションをしっかり表示するために3秒間待っています)
サンプルリポジトリ公開しています!
環境・バージョン等
macOS Sonoma 14.1.1
iOS(Simulator) 17.0
Xcode 15.0.1
Dart SDK 3.2.2
Flutter 3.16.2
画像読み込み時にキラッ✨とさせる
cached_network_image で画像(本サンプルではZennのRss Feedのenclosure)を表示します
SizedBox(
width: MediaQuery.of(context).size.width,
child: article.enclosureUrl != ''
? CachedNetworkImage(
imageUrl: article.enclosureUrl,
placeholder: (context, url) => SkeltonContainerWidget(
width: MediaQuery.of(context).size.width),
errorWidget: (context, url, error) =>
const Image(image: AssetImage('assets/no_image.png')))
: const Image(image: AssetImage('assets/no_image.png')),
)
placeholder に SkeltonAnimationを設定します
height, width等を表示する画像に合わせて調節してください
import 'package:flutter/material.dart';
import 'package:skeleton_text/skeleton_text.dart';
class SkeltonContainerWidget extends StatelessWidget {
const SkeltonContainerWidget({
super.key,
required this.width,
});
final double width;
Widget build(BuildContext context) {
return SkeletonAnimation(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10),
child: Container(
width: width,
height: 180,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(10)),
)));
}
}
イイ感じのアニメーションをつける
ここからよさげなのをjson形式でダウンロードします
サンプルで使用させていただいたのはこちらです
ダウンロードしたjsonをloading.json
としてassets
フォルダに入れ、pubspec.yml
に以下のように追記します
flutter:
assets:
- assets/loading.json
あとはloading時に呼び出すだけです!
以下ではRiverpodのAsyncValue.when
のloading
内で表示しています
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lottie/lottie.dart';
class RssFeedPage extends ConsumerWidget {
const RssFeedPage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
final selectedTopic = ref.watch(topicProvider);
final articlesAsync = ref.watch(articlesProvider(topic: selectedTopic));
return DefaultTabController(
length: topics.length,
child: Scaffold(
// 略
body: articlesAsync.when(
loading: () => Lottie.asset('assets/loading.json'),
error: (error, stackTrace) =>
Center(child: Text(error.toString())),
data: (articles) {
// 略
})));
}
}
参考にさせていただいた記事
Discussion