MDC-101 Flutter: マテリアル コンポーネント(MDC)の基本(Flutter)

マテリアル デザインと Flutter のマテリアル コンポーネントとは

マテリアル デザインは、人の目に留まる美しいデジタル プロダクトを作成するためのシステムです。一貫した一連の基本原則とコンポーネントに基づいてスタイル、ブランディング、インタラクション、モーションの統一を行うことにより、プロダクト チームは、デザインの可能性を最大限に発揮できます。

Flutter のマテリアル コンポーネントMDC-Flutter)は、設計とエンジニアリングを、アプリやプラットフォーム間で一貫したユーザー エクスペリエンスを実現するコンポーネントのライブラリと統合します。マテリアル デザイン システムが進化するにつれ、これらのコンポーネントは、Google のフロントエンド開発標準に沿った一貫性のあるピクセル パーフェクト実装となるように更新されます。MDC は Android、iOS、ウェブでも利用できます。

この Codelab では、MDC Flutter のコンポーネントを複数使用してログインページを作成します。

作成するアプリの概要

この Codelab は、衣類や生活雑貨を販売する e コマースアプリ Shrine の作成手順を説明する 4 つの Codelab のうちの最初の Codelab です。MDC-Flutter を使用して、ブランドやスタイルを反映するようにコンポーネントをカスタマイズする方法について説明します。

この Codelab では、次のもの含む Shrine 用ログインページを作成します。

  • Shrine のロゴ画像
  • アプリ名「Shrine」
  • テキスト フィールド 2 つ(ユーザー名用とパスワード用)
  • ボタン 2 つ

Android

iOS

この Codelab の MDC コンポーネント

  • テキスト フィールド
  • ボタン
  • リップル(タッチイベントに対する視覚的な形式のフィードバック)

Flutter 開発のご経験についてお答えください。

初心者 中級者 上級者

準備

Flutter でモバイルアプリを開発するには、以下の作業が必要です。

  1. Flutter SDK をダウンロードしてインストールします。
  2. Flutter SDK で PATH を更新します。
  3. Flutter プラグインと Dart プラグインとともに Android Studio をインストールするか、お好みのエディタをインストールします。
  4. Android Emulator または iOS シミュレータ(Xcode をインストールした Mac が必要)をインストールするか、物理デバイスを使用します。

Flutter のインストールについて詳しくは、スタートガイド: インストールをご覧ください。エディタの設定方法については、スタートガイド: エディタの設定をご覧ください。Android Emulator をインストールする場合は、最新のシステム イメージを備えた Pixel 3 スマートフォンなどのデフォルトのオプションを利用してください。VM アクセラレーションの有効化は、推奨されますが必須ではありません。上に述べた 4 つの手順を完了したら、Codelab を続行できます。この Codelab を完了するために必要なのは、1 つのプラットフォーム(Android または iOS)に Flutter をインストールすることだけです。

Flutter SDK が正しい状態にあることを確認する

この Codelab を先に進める前に、SDK が正しい状態にあることを確認します。Flutter SDK を以前にインストールしている場合は、flutter upgrade を使用して SDK が最新の状態であることを確認します。

 flutter upgrade

flutter upgrade を実行すると flutter doctor. が自動的に実行されます。これが最新の Flutter インストールでありアップグレードが不要だった場合は、手動で flutter doctor を実行します。設定を完了するためになんらかの依存関係をインストールする必要があるかどうかが通知されます。自分に関係がないチェックマークは無視してかまいません(たとえば、iOS 向けの開発を行う予定がない場合は Xcode を無視できます)。

 flutter doctor

よくある質問

スターター プロジェクトをダウンロード

スターター プロジェクトは material-components-flutter-codelabs-101-starter/mdc_100_series ディレクトリにあります。

GitHub からクローンを作成する

GitHub からこの Codelab のクローンを作成するには、次のコマンドを実行します。

git clone https://github.com/material-components/material-components-flutter-codelabs.git
cd material-components-flutter-codelabs/mdc_100_series
git checkout 101-starter

プロジェクトをセットアップする

以下の手順は、Android Studio(IntelliJ)を使用することを前提としています。

プロジェクトを開く

1. Android Studio を開きます。

2. ウェルカム画面が表示されたら、[Open an existing Android Studio project] をクリックします。

3. material-components-flutter-codelabs/mdc_100_series ディレクトリに移動し、[Open] をクリックします。プロジェクトが開きます。プロジェクトを一旦作成し終えるまで、Dart Analysis に表示されるエラーは無視してかまいません。

4. プロンプトが表示されたら、次の操作を行います。

  • 任意のプラットフォームやプラグインのアップデートまたは FlutterRunConfigurationType をインストールします。
  • Dart または Flutter SDK が設定されていない場合は、Flutter プラグインの Flutter SDK パスを設定します。
  • Android フレームワークを設定します。
  • [Get dependencies] または [Run ‘flutter packages get'] をクリックします。

Android Studio を再起動します。

スターター アプリを実行する

以下の手順は、Android エミュレータまたはデバイスでテストすることを前提としていますが、Xcode がインストールされている場合は、iOS シミュレータまたはデバイスでテストすることもできます。

1. デバイスまたはエミュレータを選択します。Android Emulator がまだ起動していない場合は、[Tools] -> [Android] -> [AVD Manager] を選択して仮想デバイスを作成し、エミュレータを起動します。AVD がすでに存在する場合は、次のステップに示すように、Android Studio のデバイス セレクタから直接エミュレータを起動できます(iOS シミュレータの場合、まだ起動していなければ、開発マシンで [Flutter Device Selection] -> [Open iOS Simulator] を選択してシミュレータを起動します)。

2. Flutter アプリを起動します。

  • エディタ画面上部にある [Flutter Device Selection] プルダウン メニューでデバイスを選択します(たとえば、<version> 向けにビルドされた Android SDK または iPhone SE など)。
  • Play アイコン()を押します。

これで、Shrine のログインページのスターター コードがシミュレータで動作するはずです。Shrine ロゴと、その真下に「Shrine」という名前が表示されます。

Android

iOS

コードを見てみましょう。

login.dart のウィジェット

login.dart を開きます。以下が含まれているはずです。

import 'package:flutter/material.dart';

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  // TODO: Add text editing controllers (101)
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ListView(
          padding: EdgeInsets.symmetric(horizontal: 24.0),
          children: <Widget>[
            SizedBox(height: 80.0),
            Column(
              children: <Widget>[
                Image.asset('assets/diamond.png'),
                SizedBox(height: 16.0),
                Text('SHRINE'),
              ],
            ),
            SizedBox(height: 120.0),
            // TODO: Wrap Username with AccentColorOverride (103)
            // TODO: Remove filled: true values (103)
            // TODO: Wrap Password with AccentColorOverride (103)
            // TODO: Add TextField widgets (101)
            // TODO: Add button bar (101)
          ],
        ),
      ),
    );
  }
}

// TODO: Add AccentColorOverride (103)

これには import ステートメントと 2 つの新しいクラスが含まれています。

  • import ステートメントは、このファイルにマテリアル コンポーネントを取り込みます。
  • LoginPage クラスは、シミュレータに表示されるページ全体を表します。
  • _LoginPageState クラスの build() 関数は、UI 内のすべてのウィジェットを作成する方法を制御します。

まず、ログインページにテキスト フィールドを 2 つ追加して、ユーザーがユーザー名とパスワードを入力できるようにします。フローティング ラベルを表示してタッチリップルをアクティブにする、TextField ウィジェットを使用します。

このページは主に、スクロール可能な列に子を配置する ListView で構成されています。テキスト フィールドを一番下に配置してみましょう。

TextField ウィジェットを追加する

SizedBox(height: 120.0) の後に、2 つの新しいテキスト フィールドとスペーサーを追加します。

// TODO: Add TextField widgets (101)
// [Name]
TextField(
  decoration: InputDecoration(
    filled: true,
    labelText: 'Username',
  ),
),
// spacer
SizedBox(height: 12.0),
// [Password]
TextField(
  decoration: InputDecoration(
    filled: true,
    labelText: 'Password',
  ),
  obscureText: true,
),

各テキスト フィールドには、InputDecoration ウィジェットを受け取る decoration: フィールドがあります。filled: フィールドは、テキスト フィールドのタップ ターゲット エリアを認識しやすくするために、テキスト フィールドの背景が薄く塗りつぶされていることを意味します。2 つ目のテキスト フィールドの obscureText: true 値は、ユーザーが入力した内容を自動的に点に置き換えます。これはパスワードに適しています。

プロジェクトを保存(command キー + s)すると、ホットリロードされます。

これで、「Username」と「Password」という 2 つのテキスト フィールドを備えたページが表示されます。フローティング ラベルのアニメーションを確認します。

Android

iOS

次に、ログインページに「Cancel」と「Next」という 2 つのボタンを追加します。FlatButton(マテリアル ガイドラインでは「テキストボタン」)、RaisedButton(同じく「コンテインド ボタン」)という 2 種類の MDC ボタン ウィジェットを使用します。

ButtonBar を追加する

テキスト フィールドの後、ButtonBarListView の子に追加します。

// TODO: Add button bar (101)
ButtonBar(
  // TODO: Add a beveled rectangular border to CANCEL (103)
  children: <Widget>[
    // TODO: Add buttons (101)
  ],
),

ButtonBar は、子を並べて配置します。

ボタンを追加する

次に、ButtonBar の children のリストにボタンを 2 つ追加します。

    // TODO: Add buttons (101)
    FlatButton(
      child: Text('CANCEL'),
      onPressed: () {
        // TODO: Clear the text fields (101)
      },
    ),
    // TODO: Add an elevation to NEXT (103)
    // TODO: Add a beveled rectangular border to NEXT (103)
    RaisedButton(
      child: Text('NEXT'),
      onPressed: () {
    // TODO: Show the next page (101)
      },
    ),

プロジェクトを保存します。最後のテキスト フィールドの下に、ボタンが 2 つ表示されます。

Android

iOS

ButtonBar がレイアウトを処理します。ボタンは横並びに配置されるため、現在の ButtonTheme のパディングに応じて、互いに隣り合うように表示されます(詳細については、Codelab MDC-103 をご覧ください)。

ボタンをタップすると、他に何も発生させずにインクの波紋のアニメーションが開始されます。CANCEL ボタンでテキスト フィールドをクリアし、NEXT ボタンで画面を閉じるように、匿名の onPressed: 関数に機能を追加してみましょう。

TextEditingControllers を追加する

テキスト フィールドの値をクリアできるようにするため、TextEditingControllers を追加してテキストを制御します。

_LoginPageState クラスの宣言の直下に、コントローラを final 変数として追加します。

  // TODO: Add text editing controllers (101)
  final _usernameController = TextEditingController();
  final _passwordController = TextEditingController();

最初のテキスト フィールドの controller: フィールドで、_usernameController を設定します。

// [Name]
TextField(
  controller: _usernameController,

2 つ目のテキスト フィールドの controller: フィールドで、今度は _passwordController を設定します。

// [Password]
TextField(
  controller: _passwordController,

onPressed を編集する

FlatButton の onPressed: 関数の各コントローラをクリアするコマンドを追加します。

    // TODO: Clear the text fields (101)
    _usernameController.clear();
    _passwordController.clear();

プロジェクトを保存します。これで、テキスト フィールドに何かを入力したとき、[CANCEL] を押すと各フィールドがクリアされるようになりました。

ログイン フォームはうまくできました。それでは、ユーザーに Shrine アプリの残りの部分に進んでもらいましょう。

ポップ

このビューを閉じるには、このページ(Flutter ではルートといいます)をナビゲーション スタックからポップ(削除)します。

RaisedButton の onPressed: 関数で、Navigator から最新のルートをポップします。

        // TODO: Show the next page (101)
        Navigator.pop(context);

最後に、home.dart を開き、ScaffoldresizeToAvoidBottomInsetfalse に設定します。

    return Scaffold(
      // TODO: Add app bar (102)
      // TODO: Add a grid view (102)
      body: Center(
        child: Text('You did it!'),
      ),
      // TODO: Set resizeToAvoidBottomInset (101)
      resizeToAvoidBottomInset: false,
    );

これにより、キーボードの表示によってホームページやウィジェットのサイズが変更されることがなくなります。

これで完了です。プロジェクトを保存し、[Next] をクリックします。

以上で終了です。

Android

iOS

この画面は、MDC-102 で取り組む次の Codelab の出発点となります。

テキスト フィールドとボタンを追加しましたが、レイアウト コードを考慮する必要はほとんどありませんでした。Flutter のマテリアル コンポーネントには多くのスタイルがあり、かなり簡単に画面上に配置できます。

次のステップ

テキスト フィールドとボタンはマテリアル システムの 2 つのコア コンポーネントですが、他にもたくさんあります。Flutter のマテリアル コンポーネント ライブラリにある他のウィジェットも確認してください。

あるいは、Flutter の MDC-102 で扱うコンポーネントについて、MDC-102: マテリアル デザインの構造とレイアウトをご確認ください。

次の Codelab

この Codelab を完了するためにそれなりの時間と労力を必要とした

非常にそう思う そう思う どちらとも言えない そう思わない まったくそう思わない

今後もマテリアル コンポーネントを使用したい

非常にそう思う そう思う どちらとも言えない そう思わない まったくそう思わない