Flutter 画像ロード時にプレースホルダーを表示する

June 18, 2019

Flutter アプリで画像を表示する際にロード画面を表示する方法です。

画像の表示 with ロード画面

Flutter アプリで画像を表示する方法は以前のブログで紹介しましたが、
インターネットの画像を表示する場合、少なからずダウンロードの時間が発生します。

ユーザーからすると画面にいきなり画像が表示されるので、あまりよろしくありません。

それを解決するために、画像のダウンロード中はローディングを表示(PlaceHolder)して、
ユーザーへ「今はロード中ですよ、ちょっと待ってね」と伝えることにしましょう。

FadeInImage を使う

FadeInImage を使えば簡単に実装することができます。

FadeInImage.assetNetwork(
  placeholder: 'images/loading.gif',
  image: 'https://foo.png',
);

placeholderには assets の画像を指定します。
gif 画像も可能ですので、ローディング gif 画像なら「動いている感」をユーザーに与えられますね。

imageにはダウンロード先の URL を指定します。

FadeInImage にはassetNetworkmemoryNetworkの関数があり、memory の場合はUint8Listで指定します。

コード全体

import 'package:flutter/material.dart';

class MyImageFadeinPage extends StatefulWidget {
  MyImageFadeinPage({Key key, this.title}) : super(key: key);
  final String title;

  
  _MyImageFadeinPageState createState() => _MyImageFadeinPageState();
}

class _MyImageFadeinPageState extends State<MyImageFadeinPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(children: <Widget>[
        Container(
          child: FadeInImage.assetNetwork(
            height: 400,
            placeholder: 'images/loading.gif',
            image: 'https://foo.png',
          ),
        ),
        Center(
          child: Text('Bottom Text'),
        ),
      ]),
    );
  }
}

CachedNetworkImage を使う

FadeInImage は便利ですが、ローディングは asset や memory で用意しなければいけません。

CachedNetworkImage なら placeholder にウィジェットを配置することができます。
cached_network_image | Flutter Package

さらには、失敗時画面の用意もキャッシュの利用も簡単にできます。
(あえてキャッシュを利用したくない場合のオプションは用意されていないようです)

外部プラグインですが、公式の cookbookでも紹介されています。

pubspec.yaml の編集

pubspec.yaml にcached_network_imageを追加します。

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  cached_network_image: "^0.4.0"

placeholder と errorWidget の配置

placeholdererrorWidgetにはウィジェットを配置できるので、CircularProgressIndicatorや Text などを配置することができます。

CachedNetworkImage(
        imageUrl: "http://foo.png",
        placeholder: CircularProgressIndicator(),
        errorWidget: Icon(Icons.error),
     ),

ダウンロード成功時

失敗時

コード全体

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

class MyImageCachednetworkPage extends StatefulWidget {
  MyImageCachednetworkPage({Key key, this.title}) : super(key: key);
  final String title;

  
  _MyImageCachednetworkPageState createState() =>
      _MyImageCachednetworkPageState();
}

class _MyImageCachednetworkPageState extends State<MyImageCachednetworkPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(children: <Widget>[
        Container(
          height: 400,
          child: CachedNetworkImage(
            imageUrl: "https://foo.png",
            placeholder: Center(
              child: CircularProgressIndicator(),
            ),
            errorWidget: Center(
              child: Icon(Icons.error),
            ),
          ),
        ),
        Center(
          child: Text('Bottom Text'),
        ),
      ]),
    );
  }
}

プロジェクトの全体像は GitHub に載せています。
https://github.com/hiknot/flutter-samples/tree/master/flutter_image

参考にさせていただいたサイト

Fade in images with a placeholder | Flutter

FadeInImage class - widgets library - Dart API

Work with cached images | Flutter

cached_network_image | Flutter Package


Profile picture

Twitter GitHub