3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Flutter】material.ioのadaptive系ライブラリを使用してレスポンシブなポケモン図鑑を作る

Posted at

概要

Material Designの親であるmaterial.ioがFlutterで出しているライブラリに以下のものがあります。

これらはMaterial Designのレスポンシブ対応をより便利にするものです。
通常のアプリを作る際はあまり出番はないかもしれませんが、Webアプリを作る場合などで重宝しそうです。

今回はこちらのライブラリ群を使用して、レスポンシブなポケモン図鑑を作ります。

ライブラリの説明

adaptive_breakpoints

公式の説明から。

The adaptive_breakpoints package for Flutter allows you to use the adaptive breakpoints entries from the Material Design System.

このパッケージには、Material DesignのBreakpoints、つまり画面サイズの定義が含まれています。
このパッケージを単体で使うことはあまりないと思いますが、これから紹介するパッケージ群の実装に大きく関わっているため、存在を覚えておくことは大事でしょう。

adaptive_components

公式の説明から。

The adaptive_components package for Flutter provides a set of widgets (e.g. AdaptiveColumn, AdaptiveContainer) used to implement a responsive grid layout in Material Design.

レスポンシブなグリッドデザインを実現するためのパッケージです。
以下のコンポーネントを提供します。

  • adaptive_container
  • adaptive_column

adaptive_container

画面サイズによって表示/非表示を変えるContainerになります。 constraintsに指定した画面サイズの制約に従って表示/非表示を切り替え、表示する場合はchildに指定したコンポーネントを、非表示の場合は縦横が0のLimitedBoxを返します。

        // 切り替え部分
        if (constraints.withinAdaptiveConstraint(context)) {
          return Container(
            alignment: alignment,
            padding: padding,
            color: color,
            decoration: decoration,
            foregroundDecoration: foregroundDecoration,
            transform: transform,
            clipBehavior: clipBehavior,
            height: height,
            margin: margin,
            child: child,
          );
        } else {
          /// Since this container is not within the adaptive constraints.
          /// No widget must be returned but since you can't return no widget we
          /// are returning a [LimitedBox] which is a very efficent widget.
          return LimitedBox(
            maxWidth: 0.0,
            maxHeight: 0.0,
            child: ConstrainedBox(constraints: const BoxConstraints.expand()),
          );
        }

adaptive_column

上記のAdaptiveContainerと共に使用されるコンポーネントで、画面サイズとAdaptiveContainerに設定したcolumnSpanの値に応じてレスポンシブなグリッドデザインを作ります。

パッケージのsampleを動かすと以下のような感じになります。
列ごとのColumnの最大数がスマホサイズは4、タブレットは8〜12、それ以上は12となっており、columnSpanの合計値に沿うようにレイアウトが変更されています。

adaptive_column.gif

(途中columnSpanがContainerの高さが変わっているのはテキストによるものです。)

adaptive_navigation

ナビゲーションドロワーをレスポンシブ対応するためのコンポーネントです。Component swappingの欄で示されているように、スマホサイズ、タブレットサイズ、それ以上によってNavigationの位置や大きさが変わります。

実装について

今回はadaptive_componentsを使用し、ポケモンの一覧を表示してみます。

  • PokeAPIからデータ取得
  • Riverpod + StateNotifierのMVVM構成
  • adaptive_componentsを使用してリスト表示

できたもの

adaptive_pokemon_list.gif

columnSpanを2に設定しているため、スマホサイズで1列に2つ、最大サイズで6つ表示されます。

気になった点

他のWidgetが横にある時に通常よりも1〜2個少なく表示される

内部ではMediaQuery(画面サイズ)の横幅をそのまま使っているため、他にWidgetが横にあっても、その分が考慮されず、場所がずれます。
以下はnavigationを表示した場合。

adaptive_pokemon_list_navigation.png

itemの数が中途半端だと、切り捨てられる動きがある

初代ポケモンの151匹で表示しようとしたところ、ミュウなどの最後付近のポケモンが表示されないことがあります。列ごとのColumnSpanが最大値にならないと列にならないようになってるため、全ての画面サイズに対応させる場合はアイテムの数を調整しましょう。今回はマグマラシ(No.156)までのジョウト地方のポケモンにも出張してもらいました。

おわりに

現在はあまりアップデートがされてないようですが...状況によってはかなり有用なライブラリだと思うので、今後の発展に期待したいところです🙏

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?