実践Flutter

Flutterでスマホを中心にアプリ制作していきます。

Flutterアプリの出発点・MaterialAppとScaffold

はじめに

本記事ではGUIデザインの起点となるMateraialAppウィジェットとScaffoldウィジェットについてポイントを述べていきます。

MaterialAppはGoogleが標準デザインとしてスマホアプリやウェブサービスのデザインとして広く採用しているマテリアルデザインに基づくUIを実現しやすいフレームワークを提供してくれます。

Scaffoldはその上にのせる、アプリの標準的な雛形のようなものです。アプリの上に表示されているAppBarなどはScaffoldが直接提供しています。

以前の記事でTextウィジェットを使う場合にDirectionalityウィジェットを使いましたが、MaterialAppも文字列の方向を与える機能をもっていますので、今回からはDirectionalityに代わってMaterialAppを使っていきます。

このように、よく使われるGUIのウィジェットは色々なところでMaterialAppやScaffoldの機能に依存していたりします。その影響力を使って、全体のGUIのスタイルに調和を与えるためのもの、という役割ですね。





MaterialAppとScaffold

MaterialAppはAndroidスマートフォンでお馴染みのGoogleによるマテリアルデザインのUIを実現するためのものです。

下記サンプルのように一番根本のウィジェットとして呼び出す形が定番です。

そのhome属性にScaffoldウィジェットを配置しています。これはマテリアルデザインアプリの原型を形成するものでタイトルバーの作りとアプリ本体のウィジェットを保持しています。

それぞれフルに機能を活かそうとすると様々な設定がありますが、ここでは最低限のポイントに絞ってまずサンプルを作ってみます:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home:Scaffold(
          appBar: AppBar(
            title: const Text("Flutter App"),
            actions: const [
              Padding(
                padding: EdgeInsets.only(right:10),
                child:  Icon(Icons.info)
              )
            ]
          ),
          body:Column(
                children: const [
                  Text("Hello,"),
                  Text("Flutter"),
                  Text("World"),
                ]
            )
        )
    );
  }
}

これを実行した結果は以下になります:

f:id:linkedsort:20211016182737p:plain:w400

ここで、MaterialAppで設定している「debugShowCheckedModeBanner: false」は「DEBUG」ビルドであることを示す赤いバナーを表示させないようにするためのものです。

これを指定しないと下記のようになります:

f:id:linkedsort:20211016234740p:plain:w400

右上に赤いバナーがついているのが分かると思います。これはデバッグビルドであることを示す上で有用ですが、その下のボタンの邪魔になったりしますので、ここでは消しています。

Scaffoldウィジェットの設定の冒頭ではAppBar型のデータでアプリのタイトルバーの情報を与えています。

タイトルバーの右側のアイコン表示には右側に余白を作るためにPaddingウィジェットで囲んで隙間を作っています。Paddingに変えてContainerにしてもOKです。Paddingは隙間を作るための軽量Containerです。


各種ボタンウィジェット

つぎにマテリアルデザインUIでよく使われるボタンについて見ていきます。主なボタンとしては下記のものがあります:

ウィジェット 意味
TextButton 文字だけのボタン
ElevatedButton 浮き上がっているボタン。通常のボタンのイメージ
OutlineButton 縁取り型のボタン
IconButton アイコンを表示した形のボタン
FloatingActionButton マテリアルデザイン特有のフローティングボタン。UI本体の表示とは独立に浮き上がって表示される

それぞれのボタンの表示をみるためのサンプルコードをいかに示します。前節のサンプルのうちMaterialAppの部分のみを示します。

    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home:Scaffold(
          appBar: AppBar(
            title: const Text("Flutter App"),
            actions: const [
              Padding(
                padding: EdgeInsets.only(right:10),
                child:  Icon(Icons.info)
              )
            ]
          ),
          //(1) 要素を縦並びにする
          body:Column(
                children:   [
                  //(2) 隙間を作る
                  const Padding(
                    padding: EdgeInsets.only(top:50)
                  ),
                  //(3) 要素を横並びにする
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children:[
                      //(4) ボタン4つ
                      TextButton(
                        onPressed: (){},
                        child: const Text("Hello"),
                      ),
                      ElevatedButton(
                          onPressed: (){},
                        child: const Text("Flutter"),
                      ),
                      OutlinedButton(
                        onPressed: (){},
                        child: const Text("Come in!"),
                      ),
                      IconButton(
                        onPressed: (){},
                        icon: const Icon(Icons.access_alarm)
                      )
                    ]
                  ),
                ]
            ),
          //(5) 下にあるフローティングアクションボタン
          floatingActionButton: FloatingActionButton(
            child: const Icon(Icons.add_a_photo_outlined),
            onPressed: (){},
          ),
        )
    );

これを実行した結果は以下になります:

f:id:linkedsort:20211016185517p:plain:w400

コードのポイント

(1) 要素を縦並びにする

Columnのchildrenとして与えた要素を縦に2つ並べています。下図で示すオレンジ色の領域2つです。上がPaddingウィジェット、下がRowウィジェットです。

f:id:linkedsort:20211107191146p:plain:w400

(2) 隙間を作る

隙間を作るPaddingウィジェットを入れています。これは上の図の上側のオレンジ枠にある隙間です。隙間の大きさはEdgeInsets.only(top:50)ということで、上側に50のみとっています。空白で中身がないので、ここでは上でも下でもOKです。

(3) 要素を横並びにする

縦並びの下側の四角の中が、こちらのRowウィジェットです。そのなかで4つの要素を横並びにしています。「mainAxisAlignment: MainAxisAlignment.spaceAround」は隙間の作り方、横並びの並べ方を指定するものです。これについては詳しくは別の記事で説明していきます。

ここではRowのchildren属性に4つのボタンウィジェットを与えています。

(4) ボタン4つ

4種類のボタンウィジェットを並べています。onPressed属性は今は空の関数を与えていますが、ここに押されたときに実行するコールバック関数を与えていきます。これについても別記事で実際の例で解説していきます。

(5) フローティングボタン

下にあるフローティングアクションボタンだけはColumnウィジェットの配下ではなく、Scaffoldについている属性値であることに注意してください。

この例だと分かりづらいですが、例えばScaffoldの本体がリストビューなどを画面いっぱいに表示しているときでも、その上に浮かぶ形でボタンが配置されるのがフローティングアクションボタンです。

おわりに

今回はアプリケーションのスタイルのベースになる部分のウィジェットについてポイントを説明しました。

基本的にスマホアプリを考えていく上ではMaterialAppとScaffoldはベースのところにまずは配置して、その先を考えていくという形でOKです。

これとは別にiOSスタイルのCupertino(クパチーノ)があります。iPhoneっぽいスタイルになってこれもなかなかクールです。このあたりはお好みで選択されるとよいと思います。下記のページにある動画や画像でその雰囲気が伝わると思います:


api.flutter.dev

ちなみに「クパチーノ」とは街の名前で、アップルの本社があるところです。


ja.wikipedia.org

コロナ以前は自分もよくこの界隈に行っていて、巨大なスタジアムのような円盤の建物にはびっくりしました。横から見ると通路が透けて見えていて大勢の歩く人が見えて面白い建物です。今はわかりませんが、当時は見学ツアーもあったようで、観光スポットにもなっていたようですね。

f:id:linkedsort:20211107200254j:plain