LoginSignup
8
3

More than 1 year has passed since last update.

【Flutter】Shimmerを利用してUXの高いローディング処理を実現

Posted at

インドネシアのPT.AQ Business Consulting IndonesiaでFlutterのエンジニア兼アドバイザーをしております菊池と申します。

Zennで本を出版しておりますflutter chips(30,000字程度)
image.png

Shimmerとは

データの読み込み中であることをユーザーに伝える方法の一つとして、読み込み中のコンテンツの形状に近似したUIの上に、グレー等の色でローディング状態を表現するアニメーションです。

以下、Flutter公式から参照。

実際の作成物

今回、私は実際に表示しているリストに合わせた以下のShimmerを作成いたしました。
shimmer_sample.gif

導入手順

Shimmerプラグインのダウンロード

以下をpubspec.yamlに追加

pubspec.yaml
shimmer:

ベースファイル

ベースとなる以下のファイルを作成。
私の場合は、ほぼすべてのアプリに以下のファイルをUtilフォルダ配下に作成しています。

utils/shimmer.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';

class ShimmerWidget extends StatelessWidget {
  final double width;
  final double height;
  final ShapeBorder shapeBorder;

  const ShimmerWidget.rectangular({
    this.width = double.infinity,
    required this.height,
  }) : this.shapeBorder = const RoundedRectangleBorder();

  const ShimmerWidget.circular({
    required this.width,
    required this.height,
    this.shapeBorder = const CircleBorder()
  });

  @override
  Widget build(BuildContext context) => Shimmer.fromColors(
      baseColor: Colors.grey[400]!,
      highlightColor: Colors.grey[300]!,
      child: Container(
        height: height,
        width: width,
        decoration: ShapeDecoration(
          color: Colors.grey[400],
          shape: shapeBorder
        ),
      ),
  );
}

使用方法

長方形のShimmer

ShimmerWidget.rectangular(height: 16)

楕円形のShimmer

ShimmerWidget.circular(width: 100, height: 36,
  shapeBorder: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(36/2)
  ),
),

実際のShimmerのリストファイル

class ShimmerSeatListView extends StatelessWidget {
  const ShimmerSeatListView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(SizeConfig.smallMargin),
      child: Container(
        child: Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(SizeConfig.mediumSmallMargin),
          ),
          color: ColorName.white,
          elevation: 8,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Expanded(
                child: ListTile(
                  title: ShimmerWidget.rectangular(height: 20),
                  subtitle: Padding(
                    padding: EdgeInsets.all(SizeConfig.smallestMargin),
                    child: Column(
                      children: [
                        ShimmerWidget.rectangular(height: 16),
                        SizedBox(height: SizeConfig.smallestMargin),
                        ShimmerWidget.rectangular(height: 16),
                      ],
                    ),
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(SizeConfig.mediumMargin),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    ShimmerWidget.circular(width: 100, height: 36,
                      shapeBorder: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(36/2)
                      ),
                    ),
                    SizedBox(height: SizeConfig.smallMargin),
                    ShimmerWidget.rectangular(height: 24, width: 60),
                  ],
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

参考文献

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3