Flutterで画像が存在するかどうかを画像をロードせずに調べる方法

kyamada,flutterexistsImageFile

概要

以下の Issue にある通り、Flutter には画像が存在するかどうかをチェックするメソッドはないようです。

Suggestion: Ability to check if asset exists without loading (opens in a new tab)

そこで、画像の存在チェックをするコードを自動生成するスクリプトを作成します。

事前準備

画像は Flutter プロジェクトの images ディレクトリ以下に格納しておきます。

├── images
│  ├── international.png
│  └── justify.png

dart の実行環境 (opens in a new tab)が必要なのでインストールします。

brew tap dart-lang/dart
brew install dart

実装

画像存在チェックプログラムを自動生成するための  scripts/make_exists_image_file.dart を作成します。

scripts/make_exists_image_file.dart
import 'dart:io';
 
/// lib/exists_image_file.dartを生成する
Future<void> main() async {
  final List<FileSystemEntity> imageFiles =
      await Directory('images').list().toList();
  String imagePathLines = "";
  for (var f in imageFiles) {
    imagePathLines = "$imagePathLines  '${f.path}',\n";
  }
 
  final outFile =
      File('lib/exists_image_file.dart').openWrite(mode: FileMode.write);
  outFile.write("""
/// NOTE: This class is auto generated by scripts/make_exists_image_file.dart
 
final imagePaths = [
$imagePathLines];
 
bool existsImageFile(String path) {
  return imagePaths.contains(path);
}
""");
  await outFile.close();
}

上記のスクリプトを実行します。

dart run scripts/make_exists_image_file.dart

すると、lib/exists_image_file.dart が生成されます。

lib/exists_image_file.dart
/// NOTE: This class is auto generated by scripts/make_exists_image_file.dart
 
final imagePaths = [
  'images/justify.png',
  'images/international.png',
];
 
bool existsImageFile(String path) {
  return imagePaths.contains(path);
}

使い方

画像が存在すれば Image を、存在しなければ「準備中です」の Text を表示します。

  ListView _buildListView(List<Word> words) {
    return ListView.builder(
      itemCount: words.length,
      itemBuilder: (context, index) {
        final word = words[index];
 
        var imagePath = "images/${word.spell}.png";
        Widget imageWidget = const Text("準備中");
        if (existsImageFile(imagePath)) {
          imageWidget = Image.asset(
            imagePath,
            fit: BoxFit.contain,
          );
        }
 
        return Column(children: [
          WordListTile(
              leading: Container(
                  alignment: Alignment.center,
                  height: 120.0,
                  width: 120.0,
                  child: imageWidget),

実行結果

© 品川アプリ.RSS