Flutter

【2024年版】MacでのFlutterの環境構築手順(VSCodeでの開発想定)

Flutter

お久しぶりの投稿です。

今回はMacでのFlutterの環境構築手順についてまとめたいと思います。今後Flutter開発していくエディタはVSCodeを想定しています。

(最近Macbookを新調し、改めてFlutterの環境構築を調べていましたが、記事の内容が古く、これまでの方法と異なっているものが多々あり、自分でも備忘録としてまとめようと思ったのがきっかけになります。)

この記事は2024年11月2日執筆のものです。環境構築手順は日々変化するため今の状況と相違ないか注意してください。

Flutterとは

Flutter

2018年にアプリ開発用のフレームワークとしてGoogleがリリースしたものが「Flutter」です。Flutterは「Dart」と呼ばれる、こちらもGoogleが2011年にリリースしたプログラミング言語のフレームワークになります。

環境構築手順

1. Flutterのインストール

1-1. Flutter SDKのインストール

こちらのリンクからFlutterの公式ドキュメントにアクセスし、自身のMacに合ったFlutter SDKをダウンロードします。

Flutter SDKのインストール
M1以上のMacの場合はApple Siliconになります。

1-2. developmentフォルダの作成

ホームディレクトリ直下にdevelopmentフォルダを作成します。

~ % mkdir development

1-3. Flutter SDKの格納場所の指定

インストールしたFlutter SDKを先ほど作成したdevelopmentフォルダに格納します。

~ % unzip ~/Downloads/flutter_macos_arm64_3.24.3-stable.zip \
       -d ~/development/

1-4. パスを通す

今の状態ではFlutterコマンドをターミナルで使用することができないためパスを通し、Flutterコマンドを使用できるようにします。

~ % vi ~/.zshrc
# 以下の1行を追加
export PATH=$HOME/development/flutter/bin:$PATH
~% source ~/.zshrc

2. Xcodeのインストール

2-1. Xcode Appのインストール

App Store経由でXcodeをインストールします。

Xcode Appのインストール
Xcode Appのインストールには6GB以上の空き容量が必要になります。

2-2. コマンドラインツールでの使用許可

コマンドラインツールで、先ほどインストールしたXcode Appのバージョンを使用できるように設定します。

~ % sudo sh -c 'xcode-select -s /Applications/Xcode.app/Contents/Developer && xcodebuild -runFirstLaunch'

2-3. Xcodeの使用許可承諾

Xcodeの使用許可にサインします。

~ % sudo xcodebuild -license

2-4. iOS Simulatorのインストール

iOS開発のシミュレーターをインストールします。

~ % xcodebuild -downloadPlatform iOS

3. Android Studioのインストール

3-1. Android Studioのインストール

こちらのリンクからAndroid Studioをインストールします。

Android Studioのインストール

3-2. Flutterプラグインのインストール

Android StudioのプラグインからFlutterをインストールします。

Flutterプラグインのインストール

3-3. Android SDK Command-line Toolsのインストール

Android SDK Command-line Toolsをインストールします。

Android Studioの「SDK Manager」から「SDK Tools」タブを選択し、「Android SDK Command-line Tools(latest)」にチェックを入れ「Apply」を実行します。

SDK Manager選択
Android SDK Command Line Tools

3-4. ライセンスの同意

Androidライセンスに同意します。

flutter doctor --android-licenses

4. VSCodeの拡張機能設定

拡張機能として「Flutter」と「Dart」の2つをインストールします。

Flutter
Flutter
Dart
Dart

ここまででFlutterの環境構築は完了です。

次の項目では実際にVSCodeでFlutterのシミュレーターを立ち上げ、開発ができるところまで進んでいきます。

開発手順

Flutterアプリケーションの作成

VSCodeで「Command + Shift + P」を打ち込み、コマンドパレッドを開き「Flutter」と入力します。「New Project」を選択し、さらに「Application」を選択します。

New Project
New Project
Application
Application

 

続いて、作成したアプリケーションを配置するフォルダの選択とアプリケーション名を入力します。ここまでの作業で新規アプリケーションのファイルが作成されます。

新規アプリケーション

シミュレーターの起動

初期のサンプルアプリとしてカウンターアプリが既に実装されています。シミュレーター経由でこのカウンターアプリを起動してみます。

VSCodeの右下にある「macOS(darwin)」をクリックし、「Start iOS Simulator」を選択します。数十秒〜数分待つとiPhoneのシミュレータが起動します。

シミュレーターの選択 iPhoneシミュレーター

 

シミュレーターが起動したら、VSCodeの左のアイコンから「実行とデバッグ」アイコンを選択し、「実行とデバッグ」ボタンを押下します。こちらも数十秒〜数分待つとカウンターアプリが起動します。

デバッグと実行 カウンターアプリ

 

カウンターアプリを修了したい場合はVSCodeの四角の赤アイコンを選択します。

カウンターアプリの終了

軽微な改修を加えてみる

初期コード

現状の初期コードは以下のようになっています。

// 「Material」はAndroid系統のWidget
import 'package:flutter/material.dart';

// 「Cupertino」はiOS系統のWidget
// import 'package:flutter/cupertino.dart';

// void関数は「戻り値がない」ことを示す。
// もし関数が値を返す場合には、その値の型を指定する
// 整数を返す場合はint、文字列を返す場合はStringなど
// main関数はアプリケーションのエントリーポイント
// この関数が呼び出されると、アプリケーションが起動する
// runApp関数は、引数に渡されたWidgetを画面に表示する
// この場合、MyAppクラスのインスタンスを引数に渡している
// constを使ってMyAppインスタンスを生成している
// MyAppが定数インスタンスとして生成されるため、再レンダリングが不要な場合に効率的に処理される
void main() {
  runApp(const MyApp());
}

// MyAppクラスはStatelessWidgetクラスを継承している
// 「状態を持たない」Widgetを作成するために使用される
// ユーザーの操作によって変化するデータを持たない場合に使用される
class MyApp extends StatelessWidget {
  // constを使ってMyAppインスタンスを生成している
  // {super.key}は、親クラス(StatelessWidget)のkeyパラメータを受け取る
  // superは「親クラス」を指し、keyはStatelessWidgetが持つパラメータの一つ
  // keyはWidgetの一意性を管理するためのIDとして使われ、ツリー構造のWidgetを識別する
  // const MyApp({super.key});は、定数コンストラクタであるMyAppクラスのコンストラクタで、
  // 親クラスのkeyを直接受け取り、MyAppインスタンスを一意に管理するための役割を持つ
  const MyApp({super.key});

  // StatelessWidgetクラスから継承されたbuildメソッドをオーバーライドしている
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo', // アプリのタイトル
      theme: ThemeData(
        // アプリのカラースキーム
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        // Material Design3を有効化
        useMaterial3: true,
      ),
      // homeプロパティでアプリのホーム画面を設定
      // MyHomePageクラスを指定し、タイトルとして"Flutter Demo Home Page"を渡している
      // MyHomePageはこのアプリが起動した際に最初に表示される画面
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

// MyHomePageクラスはStatefulWidgetクラスを継承している
// 「状態を持つ」Widgetを作成するために使用される
// ユーザーの操作によって変化するデータを持つ場合に使用される
class MyHomePage extends StatefulWidget {
  // {super.key, required this.title}は、keyとtitleの2つの引数を受け取る
  // super.keyは、親クラスStatefulWidgetのkeyに値を渡すために使われ、
  // FlutterのWidgetツリー内でWidgetを一意に識別するために利用される
  // required this.titleは、必須の引数titleを設定する
  const MyHomePage({super.key, required this.title});

  // titleプロパティをfinalで宣言する
  // このプロパティは変更できない固定の値で、コンストラクタで一度設定されるとその後変更されない
  final String title;

  // State<MyHomePage>を作成するメソッドであるcreateStateをオーバーライドする
  @override
  // createStateメソッドはStatefulWidgetに必須のメソッド
  // 対応する状態クラスである_MyHomePageStateクラス(Stateオブジェクト)を返す
  // アンダーバーをつけることでそのメソッドはプライベートになる
  State<MyHomePage> createState() => _MyHomePageState();
}

// State<MyHomePage>を継承することで、このクラスはMyHomePage Widgetと連動する
// StatefulWidgetであるMyHomePageの状態を保持し、必要に応じて再描画を行う
class _MyHomePageState extends State<MyHomePage> {
  // _counterはint型の整数で、初期値は0に設定されている
  // アンダーバーが付いているのでプライベート変数として定義されている
  int _counter = 0;

  // カウンターを増加させるメソッド
  // アンダーバーが付いているのでプライベート変数として定義されている
  void _incrementCounter() {
    // setStateメソッドは状態が変化したことを通知し、Widgetを再描画するために使用する
    // setStateを呼び出さずに_counterを更新した場合、変更が表示されない
    setState(() {
      // _counterを1ずつ増加させる
      // アンダーバーが付いているのでプライベート変数として定義されている
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // Scaffoldは、Flutterアプリの基本的なレイアウト構造を提供するウィジェット
    // appBar/body/floatingActionButtonプロパティを使って、各部分を簡単に設定できる
    return Scaffold(
      // AppBarはアプリ画面の上部に表示されるバー
      // ここではアプリのタイトルや背景色が設定される
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      // bodyは画面の中央部分のレイアウトを構成
      // Center Widgetは、指定した子Widgetを中央に配置するためのWidget
      body: Center(
        // Column Widgetは、複数の子Widgetを縦方向に並べるためのレイアウトWidget
        child: Column(
          // MainAxisAlignment.centerにより、縦方向の中央に配置する
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // 初期表示のテキスト
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              // 文字列内に変数を埋め込むため$を使用する
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      // floatingActionButtonは画面右下に表示されるボタン
      floatingActionButton: FloatingActionButton(
        // ボタンが押されると_incrementCounterメソッドが呼ばれ、カウンターが増加する
        onPressed: _incrementCounter,
        // ボタンのツールチップ(ホバーまたは長押しで表示される説明)
        tooltip: 'Increment',
        // ボタンにプラスアイコンを設定
        child: const Icon(Icons.add),
      ),
    );
  }
}

ヘッダータイトルの変更

ヘッダータイトルを「Flutterヘッダー」に変更します。

- home: const MyHomePage(title: 'Flutter Demo Home Page'),
+ home: const MyHomePage(title: 'Flutterヘッダー'),

画面中央のテキスト変更

画面中央のテキストを「Hello Flutter!」に変更します。

- const Text(
-   'You have pushed the button this many times:',
- ),

+ const Text(
+   'Hello Flutter!',
+ ),

全体色の変更

全体のカラーを青系統に変更します。

- colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
+ colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueAccent),

ヘッダーにプラスアイコンを付与

ヘッダーにプラスアイコンを付与し、このアイコンをクリックしてもインクリメントされるように変更します。

- appBar: AppBar(
-   backgroundColor: Theme.of(context).colorScheme.inversePrimary,
-   title: Text(widget.title),
- ),

+ appBar: AppBar(
+   backgroundColor: Theme.of(context).colorScheme.inversePrimary,
+   title: Text(widget.title),
+   IconButton(
+     icon: const Icon(Icons.add),
+     onPressed: _incrementCounter,
+   ),
+ ),

ヘッダータイトルを左寄せ

ヘッダーのタイトルを左寄せに修正します。

- title: Text(widget.title),

+ title: Align(
+ alignment: Alignment.centerLeft,
+   child: Text(widget.title),
+ ),

画面中央にテキストを追加

画面中央部に縦並びになるようにテキストを1行追加します。

+ const Text(
+   'カウンターが1ずつ増加します',
+ ),

Hello Flutter!のフォントサイズ修正

画面中央部に表示されている「Hello Flutter!」のフォントサイズを変更します。

- const Text(
-   'Hello Flutter!',
- ),

+ const Text(
+   'Hello Flutter!',
+ ),

decrementのボタンを追加する

現状、インクリメントするボタンしか表示されていません。デクリメントする(カウントダウンする)ボタンを追加します。

// カウンターを減少させるメソッド
// アンダーバーが付いているのでプライベート変数として定義されている
void _decrementCounter() {
  // setStateメソッドは状態が変化したことを通知し、Widgetを再描画するために使用する
  // setStateを呼び出さずに_counterを更新した場合、変更が表示されない
  setState(() {
    // _counterを1ずつ減少させる
    // アンダーバーが付いているのでプライベート変数として定義されている
    _counter--;
  });
}

floatingActionButton: Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: <Widget>[
    FloatingActionButton(
      onPressed: _decrementCounter,
      tooltip: 'Decrement',
      child: const Icon(Icons.remove),
     ),
    const SizedBox(width: 10),
    FloatingActionButton(
      onPressed: _incrementCounter,
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ),
   ],
),

挙動確認

ここまで修正すると以下のような画面になります。

動作チェック

参考

Docs | Flutter

 

今回はMacでのFlutterの環境構築手順についてまとめました。今後はFlutter開発の記事を中心に書いていこうと思っています。