iOS Android

Flutter開発のはじめかた 開発環境セットアップ〜Widtgetの解説

投稿日:2020年2月17日 更新日:

はじめに

Flutterとは、マルチプラットフォームで動作するUIフレームワークです。単一のソースコードからiOS/Android/Web/デスクトップ用にコンパイルすることが可能です。様々な「ウィジェット」と呼ばれるUIパーツが初めから用意されており、それを組み合わせることで、簡単に美しいUIを実装することができます。
プログラミング言語には「Dart」を使用します。Dartは、元々JavaScriptを置き換える目的で開発された言語ですが、今ではFlutterで使用できることで有名です。今回は、Dartの説明はあまり深掘りしませんが、JavaScriptやJavaをやったことのある開発者であれば、すんなり理解できると思います。

セットアップ

Flutterのインストール

Flutterはこちらからインストールできます。インストール方法は各OSにより異なりますが、ここではmacOSでのインストール方法を説明します。
https://flutter.dev/docs/get-started/install

まず、Flutterのリポジトリをクローンします

次に、パスを通します。bashの場合は ~/.bash_profile 、zshの場合は ~/.zshenv に記述します。

source コマンドでパスを読み込むか、ターミナルを再起動して、dockerのコマンドを試してみましょう。

このコマンドは開発環境をチェックし、必要なセットアップを表示してくれます。それでは、進めていきましょう。
(Dart SDKはFlutterに含まれているため、セットアップは不要です。)

Android環境のセットアップ

Android Studioに含まれているAndroid SDKを使用します。以下からAndroid Studioをインストールしてください。
https://developer.android.com/studio/?hl=ja
インストール後、Android Studioを起動し、セットアップウィザードに従い、Android SDKをインストールしてください。
(Android Studioは、後ほどIDEとして使用します。)

Xcodeのインストール

iOS ビルドにはXcodeをインストールします。(Mac AppStoreからインストールしてください。)
インストール後、コマンドラインツールの設定を行います。

ライセンスに同意し、セットアップを進めてください。

IDEのセットアップ(Android Studio)

Flutterの開発環境として、Android StudioもしくはVisual Studio Codeが推奨されています。いずれも、Flutterプラグインを導入することで、Flutterのデバッグ・ホットリロードができるようになります。
今回は、Android Studioでのセットアップ方法を紹介します。

  1. Android Studioを起動し、Preferences画面を開きます。(Welcome画面 > Configure > Preferences)
  2. Editor > Pluginsを開き、検索ボックスで flutter と検索します。
  3. Flutterプラグインの Install ボタンでインストールします。
  4. 途中、Dart Pluginのインストールを尋ねるプロンプトが表示された場合は、「Yes」ボタンでインストールします。
  5. 指示に従ってAndroid Studioを再起動します。

以上で、IDEのセットアップは完了です。これで、Android Studio上でFlutter開発を一通り行う準備ができました。

Flutterプロジェクトの新規作成

  1. Android StudioのWelcome画面で「Start a new Flutter Project」を選択します。
  2. ベースとなるプロジェクトを以下の中から選択します。
    • Flutter Application
      ユーザ向けのアプリを開発する際に選択。
    • Flutter Plugin
      AndroidやiOSのネイティブAPIをFlutterから使用できるようにするプラグインを開発
    • Flutter Package
      Dartコンポーネントを作成するために使用します。例えば、自作のWidgetを、複数のプロジェクトで共有する場合に使用できます。
    • Flutter Module
      既存のAndroid/iOSアプリにFlutterコンポーネントを組み込むモジュールを開発する場合に使用します。
  3. プロジェクト設定を行います。
    Project name、Project locationを入力して進みます。Project nameはスネークケースで入力しましょう。
  4. パッケージネームの設定をします。
    Company domainは、パッケージ名に使用する企業名を指定します。Androidでのパッケージ名、iOSでのBundle Identifierで同じ値が使用されます。
    Android X、Kotlin support、Swift supportにチェックを入れます。

iOS実機ビルド

iOS実機ビルドを行うため、署名設定を行います。

  1. Flutterプロジェクト内の ios/Runner.xcworkspace をXcodeで開きます。
  2. プロジェクト設定の “Signing & Capabilities” を開き、チーム設定等の署名設定を行います。ここは、通常のiOSアプリ開発と同じです。

この後、Android Studioで接続された実機を選択し、Runをクリックすると、実機でFlutterアプリが起動します。

Android実機ビルド

Androidの実機を接続し、iOSと同じように実機を選択し、Runすると起動します。

ホットリロード・ホットリスタート

Flutterの開発中の便利機能として、ホットリロードがあります。これは、コードをSaveすると、デバッグ中のアプリがランタイムで更新され、最新のコードが適用される機能です。
一方で、ホットリスタートは、一般的なAndroid/iOSアプリ開発と同じように、アプリをRunし直すことで、最新のコードを適用する方法です。
レイアウト変更などの、軽微な変更はホットリロードが効きますが、変更内容によってはホットリロードが効かない場合もあります。そのような場合は、ホットリスタートを行いましょう。(Android Studioであれば、 Ctrl + r でホットリスタートです)

Flutterプロジェクトの構成

Flutterプロジェクトでは、主に以下のディレクトリ・ファイルを開発に使用します。

  • lib/
    Dartコードを記載するディレクトリです。
  • test/
    Dartのテストコードを配置するディレクトリです。
  • ios/
    Xcodeプロジェクトが配置されるディレクトリです。
  • android/
    Androidプロジェクトが配置されるディレクトリです。
  • pubspec.yaml
    外部ライブラリを導入したり、アセットを登録する際に使用します。

Widgetツリー構造

Flutterでは、UIをWidgetという単位で構築し、アプリのルートから全てツリー構造となっています。
以下に、プロジェクト作成直後のWidgetツリーを図にしました。

ルートは MaterialApp Widgetとなり、 home に渡すWidgetが、初期画面となります。ここでは、 MyHomePage を設定し、さらにその下に画面に表示するUIがツリーとなっています。

MyHomePage 直下の Scaffold は、1画面を構成する土台です。 AppBar , Body , FloatingActionButton などの枠にWidgetを当てはめることで、簡単にアプリのUIを構築できます。大抵の場合は、 Scaffold を使用することをお勧めします。

1画面に必要なクラス

それでは、このツリー構造をクラスで表すと、どのようになるでしょうか。
まず、画面が「動的に変化するかどうか」で大きく分かれます。動的に変化する画面の場合、 StatefulWidget を継承したクラスを作成します。逆に、静的な画面であれば、 StatelessWidget を継承したクラスを使用します。

StatefulWidgetを使用した画面の作り方

StatefulWidget を使用する場合は、次の2つのクラスが必要です。

  • StatefulWidget を継承したクラス
  • State<T> を継承したクラス

プロジェクト作成直後のコードを例に、解説します。まずは、 StatefulWidget を継承した MyHomePage クラスを見てみましょう。
ccreateState() をオーバーライドし、後述する State<T> のインスタンスをセットします。

次に、 State<T> を継承した _MyHomePageState クラスを見ていきましょう。
まず、状態を保持しておくフィールド変数を定義します。 build() メソッドで、フィールド変数を使用して、Widgetを構築していきます。
フィールド変数を更新するときは、 setState() のクロージャ内で変数を更新すると、 Widget build(BuildContext context) がコールされWidgetが再構築されることで、UIが更新されます。

 

StatelessWidgetを使用した画面の作り方

StatelessWidget を継承したクラスを作成します。 StatelessWidget は状態を変化させることができません。そのため、 State<T> クラスは不要で、直接 build() メソッドを実装します。

 

画面遷移

画面遷移を行うには、 Navigator クラスを使用します。

Push/Pop

画面遷移するには、 Navigator.push() メソッドを使用します。第2引数で MaterialPageRoute クラスを使い、次の画面のインスタンスを生成して渡します。

前の画面に戻るには Navigator.pop(context) と実装すればOKです。また、Push遷移すると、左上に戻るボタンが表示されるため、この機能で十分であれば、Pop遷移の実装は必要ありません。

Modal

モーダル遷移の場合も Navigator.push() を使用します。 fullscreenDialog 引数を true に設定すると、モーダル遷移になります。

値の渡し方

次の画面に値を渡すには、遷移先でプロパティを定義し、コンストラクタで値を渡します。
まず、遷移先のコードです。

name をコンストラクタで受けとり、 Widget build(BuildContext context) 内でテキスト表示しています。
プロパティを final としているため、コンストラクタの実装が必須となります。(ただし、後からプロパティの値を変更する場合は、 final を付ける必要はありません)
次に、遷移元です。

プロジェクトテンプレートのHomePageを変更し、次の画面に値を渡すようにしました。
値を渡す際は、 MaterialPageRotue() で次の画面を生成する際、コンストラクタに値を渡すことで、実現できます。

値の戻し方

値を戻す際は、 Navigator.pop() メソッドに値を渡します。

次に、戻した値を受け取る実装です。

このサンプルでは、戻ってきた値を使用し、ボタンのテキストを変化させるようにしました。
戻り値の受取は非同期となるため、 await を使用します。また、 await を使用する場合は、関数を async とします。

Widget

Widgetは、FlutterのUIを定義するオブジェクトです。Widgetの特徴としては、UIのほぼ全てをWidgetやそのツリーで構成されていることが挙げられます。
また、ユーザ操作に対するレスポンスが優れているUI/UXが、Widgetとして数多く存在しています。また、その多くはカスタマイズ可能であり、もちろん自作のWidgetを作成することも可能です。
ここでは、使用頻度の高いWidgetを紹介します

レイアウト

Scaffold

画面の骨組みとなるレイアウトです。AppBar, FAB, BottomNavigationといった、基本的なUIの骨組みを提供します。基本的に、各画面のルートWidgetは、Scaffoldを使用することをお勧めします。

画面内のコンテンツは body に実装します。直接、UIパーツを置くと、1つしか配置できないため、後ほど説明する Column などを使用して、複数配置できるようにすることがほとんどです。

Container

様々な用途で使用できる、便利なWidgetです。色付きのボックス、サークルを作成したり、それを回転したりすることができ、柔軟にUIを表現することができます。

円形にするには、このようにします。

実行結果は次のようになります。

BoxDecoration クラスを使用して、円形を指定します。このとき、 Containercolor 引数は渡さず、 BoxDecorationcolor を渡す必要があるため、注意してください。

Center

子Widgetをセンタリングして表示したいときに使用します。

childColumnRow といった、複数のWidgetを表示できるWidgetを渡すことで、複数パーツをセンタリングすることも可能です。

Column

UIパーツを縦に並べたいときに使用します。使い方はシンプルです。

Columnでは、子Widgetを複数持つことができるため、引数名が children となり、Widget配列を渡します。

Row

UIパーツを横に並べたいときに使用します。

mainAxisAlignment: MainAxisAlignment.spaceEvenly とすることで、均等にスペースを取るようにしています。

UIパーツ

Text

テキストを表示するために使用します。

ほとんどは、第一引数のテキスト指定のみで済みますが、フォントスタイルを設定したい場合は、 style 引数に TextStyle を渡します。
TextStyle では、フォントサイズ、太字・イタリック、カラーなどを設定できます。

Image

画像を表示するWidgetです。
まずは、アプリ埋め込みのアセットを表示する方法です。アセットを表示するには、画像を配置した後、 pubspec.yaml で登録する必要があります。

登録したアセットを表示するには、以下にようにします。

引数に、 pubspec.yaml で記載した画像のパスを渡します。

また、URLを指定して、画像をダウンロードして読み込むこともできます。

Flutterサンプルでお馴染みのフクロウが表示されます。

RaisedButton

立体的なボタンを表示します。テキストボタンの他に、 icon() ファクトリメソッドを使用することで、アイコン付きのボタンを表示することができます。

ボタンが押された時の処理は onPressed に、クロージャとして記載します。以下のように、別メソッドを作成して、呼び出すことも可能です。

なお、 StatelessWIdget では、 Widget build(BuildContext context) 以外でBuildContextを取得することはできないため、ボタンタップ時にBuildContextが必要な場合(画面遷移など)は、クロージャで書くようにしてください。

TextField

TextFieldはテキスト入力UIを提供するWidgetです。

onSubmitted を実装し、入力した値を受け取ります。
また、 decoration 引数に InputDecoration クラスを設定することで、TextFieldの見た目を設定できます。 このサンプルでは、 labelText ではプレースホルダーを設定します。その他にも、 border: OutlineInputBorder() とすることで、枠付きの見た目にすることも可能です。

AppBar

AppBarは、画面上部に表示されるヘッダーです。

Scaffoldの apppBar 引数に渡します。 actionsIconButton を渡すと 、AppBar右側にボタンを追加することができます。

BottomNavigationBar

画面下部にタブのようなUIを表示することができます。

BottomNavigationを実装する際は、画面を切り替える処理は自分で実装する必要がある点に気をつけてください。今回の場合、画面のインスタンスを _children 配列に保持し、Scaffoldで body: _children[_currentIndex], と渡すようにしています。
そして、BottomNavigationBarがタップされたときに呼ばれる _onBottomNavigationBarTap(int index) で、 _currentIndex を変更することで、画面を更新し、タブが切り替わったように見せています。そのため、BottomNavigationを使用する画面では、StatefulWidgetとなります。

自作Widgetの作り方

同じレイアウトを使いまわしたいときに、自作Widgetを作成するには、StatelessWiidgetもしくはStatefulWidgetを継承したクラスを作成します。

onPressedとchildは外部から設定できるよう、プロパティとコンストラクタを実装しています。そのほかは、これまで紹介したWidgetと同じように、 Widget build(BuildContext context) でWidgetを返却するようにします。

おまけ(PlantUML)

冒頭で示したWidgetツリー図は、PlantUMLで作成しました。記事画像用なので特にコードの整理はしていませんが、参考になればと思い、PlantUMLのコードを公開します。
ちなみに、冒頭で skinparam shadowing false とすることで、デフォルトで描画される影を消去しています。

 

さいごに

Flutterは様々なWigetが用意されているされており、Wigetを組み合わせることでスピーディにクロスプラットフォームアプリが実現出来ることが分かりました。今後活用していきたいも思います!

おすすめ書籍

基礎から学ぶ Flutter Flutter モバイルアプリ開発バイブル プログラミング言語Dart

blog-page_footer_336




blog-page_footer_336




-iOS, Android
-, , ,

執筆者:


comment

メールアドレスが公開されることはありません。

CAPTCHA


関連記事

swift

[Swift]iPadのActionSheet表示でクラッシュする問題

1 はじめに2 エラー内容2.1 エラー原因2.2 まだこれで解決ではない3 さいごに はじめに こんにちは、nukkyです。 私は普段iPhoneアプリの開発を主に行っているのですが 慣れか油断かi ...

swift

SwiftでのDateクラスの煩わしさから解放されるSwiftDateを使ってみた

1 はじめに2 準備3 使ってみよう3.1 現在の取得3.2 パラメータの取得3.3 パラメータの操作3.4 文字列変換3.5 Dateの比較3.6 判定メソッド4 さいごに はじめに こんにちは、n ...

Xcode11のデバッグ機能

1 はじめに2 Device Conditions2.1 Thermal state condition2.2 Network link condition3 Environment Override ...

swift

[iOS]意外と簡単ウィジェット機能を実装してみる

1 はじめに2 OSごとのできること3 ウィジェットの実装3.1 Today Extensionの追加3.2 Chartを表示3.3 表示を増やす3.4 ウィジェットをタップした際にアプリを起動する4 ...

SafetyNet Attestation APIでRoot化チェック【基本的な検証編】

1 はじめに2 SafetyNet Attestation APIとは2.1 注意点2.1.1 レスポンス結果はアプリ内で判定しない2.1.2 JWSのキーチェーンをチェックする2.1.3 レスポンス ...

フォロー

blog-page_side_responsive

2020年2月
 1
2345678
9101112131415
16171819202122
23242526272829

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。