Flutterハンズオン（超入門）

# Flutterって何？

```wikipedia
Flutter (フラッター) は、Googleによって開発されたフリーかつオープンソースの
モバイルアプリケーションフレームワークである。FlutterはAndroidやiOS向けの
アプリケーションの開発に利用されている。Fuchsiaではアプリケーションの開発
は主にFlutterを利用して行われている[4]。

2018年12月4日、ロンドンで開催されたFlutter Live '18にて、初の正式版となる
Flutter 1.0のリリースが発表された[5]。
```

最も重要なことは、「マルチプラットフォーム」の開発ができるフレームワークであるということです。

作りたいアプリがある場合に、通常の開発であれば、動作させる環境毎に言語・開発環境が異なります。その為、全ての環境のアプリケーションを作るには、それぞれ技術を保有する人材が必要となり１つのアプリを作るコストが大きくなります。
新規事業で、新しいアプリケーションを作る場合にブラウザ（WEB）アプリケーションが多いのは、動作させるブラウザがAndroid、iPhone、Windows、Macをカバーしている為、１つのブラウザ（WEB）アプリケーションを作るだけで実現でき比較的難易度が低いから選定されています。

<img width="960" alt="image.png (127.7 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/15/66117/98889f67-12cf-4ef5-8596-a276767bc1e7.png">


Flutterでは、Dart言語とFlutterFWで、全てのアプリケーションを作成可能であり、開発コストを大幅に削減することが可能です。
<img width="960" alt="image.png (81.1 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/15/66117/0670afb3-f497-4c20-8657-8abb15678220.png">


OS固有の技術を利用する場合は、KotlinやSwift、C++などで拡張する必要があります。
どんなことを実現したいアプリケーションなのかで、利用技術を選定してください。


# ハンズオンのゴール
Flutterでの開発方法、動作確認を学ぶ
開発選択肢の１つに加えてもらう

# Step
1. 環境構築（Mac／Windows）
    - 所要時間：45分
1. HelloWorld
    - 所要時間：15分
1. ボタンを配置してみる
    - 所要時間：15分
1. 画面遷移してみる
    - 所要時間：15分

# 環境構築（Mac／Windows）
    - 所要時間：45分

この作業のゴール：Mac
<img width="1234" alt="image.png (575.8 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/16/66117/fbff120d-3a49-49fa-98f9-17e53814e4b3.png">

この作業のゴール：Windows
<img width="1760" alt="image.png (112.4 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/16/66117/1445bae9-c41e-44f2-913c-a14c23946d2b.png">


1. Flutter SDKをインストールする
    1. https://flutter.dev/docs/get-started/install
        - MacOS

            ```
            cd ~/development
            unzip ~/Downloads/flutter_macos_1.22.6-stable.zip

            export PATH="$PATH:`pwd`/flutter/bin"
            ```
        - Windows


            ```
            C:\src\flutter あたりに解凍
            ```
            c:\src\flutter\flutter_console.bat を実行
            <img width="1862" alt="image.png (166.3 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/16/66117/2d5857d4-6068-48ae-a11b-9111f813924f.png">

1. FlutterでWindows/Macを有効にする


    ```
    flutter channel dev
    flutter upgrade
    flutter config --enable-windows-desktop
    flutter config --enable-macos-desktop
    ```

1. Flutter doctorで必要なアプリケーションをインストールする

    ```
    flutter doctor
    ```
    - MacOS
        - Android Studio
            - Dart/Flutterプラグイン設定
        - Xcode
        - VS Code
            - Dart/Flutterプラグイン設定
        - Chrome
    - Windows
        - Android Studio
            - Dart/Flutterプラグイン設定
        - VS Code
            - Dart/Flutterプラグイン設定
        - Visual Studio
            - C++ (WindowsDesktopアプリケーション開発環境)
        - Chrome

# HelloWorld
    - 所要時間：15分

## プロジェクトを作成し、VSCodeで表示

プロジェクト作成

```bash
flutter create handson
```

<img width="1594" alt="image.png (1.1 MB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/fecf5fa4-726b-429b-a63d-ad6fb484bbb8.png">

<img width="2322" alt="image.png (201.4 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/1435dffe-3333-41b7-a6ee-0c1ee69cb155.png">

## Flutterのディレクトリ構造説明

- pubspec.yaml
   <img width="2330" alt="image.png (487.6 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/9950fc12-11e3-4a77-8008-8d4bb0195ba2.png">
    - プロジェクト定義ファイル
        - 類似
            - Node.js - package.json
            - PHP Larabel - composer.json
            - Python - requirements.txt
- lib/*
  <img width="2330" alt="image.png (496.9 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/e6cb7c74-ca17-4017-93ac-6e8b748f61c9.png">
    - Flutterの実行ロジックを格納するディレクトリ
    - 最初に読み込みされるファイルは、`lib/main.dart`
- test/*    , integration_test/*
    <img width="2328" alt="image.png (463.1 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/65fdb4b6-d0d0-4b3b-9b39-afa6bcb6e280.png">
    - Flutterのテストロジックを格納するディレクトリ
- android/* , ios/* , macos/* , web/* , windows/*
    <img width="2330" alt="image.png (455.0 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/890b034e-43e1-4f93-a11d-cb3e43395323.png">
    - 実行環境毎の定義ファイルや、拡張ロジックを格納するディレクトリ
    - アプリ系（android/iso/macos）などのマイク機能、カメラ機能を利用します。などの許可定義などもここ
    - ビルド定義もここになるので、うまくビルドが通らない時は、このディレクトリのファイルを変更する
- build/*
    <img width="2328" alt="image.png (441.1 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/e5734463-17d1-4229-90f3-37165b334dbb.png">
    - ビルドで作成された実行ファイルが格納されるディレクトリ


## Flutterを実行してみる

```
flutter run 
# macos
flutter run -d macos

# windows
flutter run -d windows

# chrome
flutter run -d chrome

# ios
open -a simulator 
flutter run
```

<img width="2988" alt="image.png (863.8 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/84b3a7a9-f772-4d15-87e9-7101d7ca2551.png">

## HelloWorldの文字を追加してみる

```dart:lib/main.dart
            Text(
              'Hello World!!!',
            ),
```

- `main.dart` ファイルを開いて、９５行目あたりにのTextを１つ追加する。
    <img width="1534" alt="image.png (164.4 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/6fde40b7-3233-48ec-a02c-cda39a5082e0.png">

- コマンドプロンプト・ターミナルでホットリロード `shift + r` を実行
    <img width="3006" alt="image.png (946.9 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/172e2a2f-98e4-46aa-9b84-e23c3c52c04d.png">

# ボタンを配置してみる
    - 所要時間：15分

```dart:lib/main.dart
            RaisedButton(
              child: Text('ボタンです！'),
              onPressed: () {},
            ),
```

- `main.dart` のHello WorldのText要素の下に、RaisedButtonを配置してみる。
    <img width="3006" alt="image.png (830.9 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/653dd287-c766-4c09-ace3-dc82d7bb9e71.png">

```dart:lib/main.dart
            RaisedButton(
              child: Text('ボタンです！'),
              onPressed: () => showDialog(
                context: context,
                builder: (_) {
                  return AlertDialog(
                    title: Text("message"),
                    content: Text("Flutterって面白い！"),
                    actions: <Widget>[
                      // ボタン領域
                      FlatButton(
                        child: Text("閉じる"),
                        onPressed: () => Navigator.pop(context),
                      ),
                    ],
                  );
                },
              ),
            ),
```

- ボタンを押下したときの、アクション `onPressed` を追加してみる。
    <img width="3000" alt="image.png (795.1 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/17/66117/38a40ae8-96f8-4368-bf59-0c3644d6e523.png">


# 画面遷移してみる
    - 所要時間：15分

## 遷移先の画面作成

```dart:sub_container.dart
import 'package:flutter/material.dart';

class SubPage extends StatefulWidget {
  @override
  _SubPageState createState() => _SubPageState();
}

class _SubPageState extends State<SubPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Subページです'),
      ),
      body: const Text('Subページです!!'),
    );
  }
}

```
- `lib/sub_container.dart` で新規ファイルを作成する。
    <img width="2482" alt="image.png (463.9 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/18/66117/ffc92eca-04a0-4391-9e29-0b548d5c4511.png">


## 遷移処理の追加

```dart:lib/main.dart
import 'sub_container.dart';
```

- 作成したファイルをimport
    <img width="1668" alt="image.png (106.2 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/18/66117/0edecedb-79ae-4f6c-bcbe-5e5c091ab308.png">


```dart:lib/main.dart
      routes: <String, WidgetBuilder>{
        '/sub': (BuildContext context) => (SubPage()),
      },
```

- 画面遷移を担う、routesを設定
    <img width="1648" alt="image.png (222.8 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/18/66117/a9b18fe0-308b-429e-80ae-d53eb6f68aa0.png">



```dart:lib/main.dart
            RaisedButton(
              splashColor: Colors.purple,
              child: Text('Subページに移動'),
              onPressed: () => {Navigator.pushNamed(context, '/sub')},
            ),
```

- 遷移用のボタンを追加
    <img width="1690" alt="image.png (220.7 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/18/66117/78d41a01-7335-4224-b4a5-77695f4154b7.png">

## 動かしてみる
<img width="3148" alt="image.png (816.1 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/18/66117/008d28d7-9aa0-407f-a51f-f40361230379.png">

<img width="3152" alt="image.png (812.3 kB)" src="https://img.esa.io/uploads/production/attachments/6882/2021/02/18/66117/f768bb2e-874e-4276-b3c0-369b189da34f.png">

# 締め
Flutterの技術記事は増えてきているので、調べてみるといろいろ出てきます。
私が学習に利用したサイトを紹介します。

- https://flutter.dev/docs
    - 公式ドキュメント
- https://pub.flutter-io.cn/
    - Dart/Flutterのパッケージサイト
- Qiita&GitHub
    - 動くものをローカルにクローンして手当たり次第に実行

Flutter/Dartは、Reactをオブジェクト指向にした感じだなーと。
マルチプラットフォームで動かせることは、非常に魅力的な要素なので少しアプリ作ってみるときにFlutterってあったな〜と思い出してもらえれば幸いです。