"Simple" is "Best"

開発時に詰まったところや 調べた結果日本語での情報が無かったり古かったりした場合に自分用のメモとして高校生(?)が更新していくブログ

Flutterをいじってみよう

この記事は以下のカレンダーの19日目の記事です

qiita.com

 

 去年は受験があったんで今回が初アドカレです

温かい目で見守ってください

 

ちょっと前にGoogle DevFest Kyoto 2017に参加しまして

その時にこのFlutterというものに出会いました

いつかDevFestでやったハンズオンのまとめを書きたいな~と思っていたら

ちょうどアドカレの季節だったんで勢いで記事にしました

今回は触りだけやってみます

公式サイトは以下

Easy and fast SDK for beautiful apps - Flutter

わからなくなったら公式を読みましょう

 

最近プログラミング界隈に入ってきたって言う人にはちょっと濃いかも

 

Flutter(+Dart)ってなんぞや?

FlutterというものはGoogleさんが作成しましたFrameworkです

Dartと呼ばれる言語(これもGoogle製)を用いて

AndroidiOSの両方のアプリを一つのコードで作成します

Dartについて気になる方はぜひGoogle大先生に聞いてください

Javaやってる方にとってはあまり苦なく書けると思いますし

多少OOPを触っている方ならコードを見ればすぐに理解できます

 

とりあえず環境構築

今回はAndroidStudio 3.0.1 on Win10な環境でやっていきます

事前にGit for Windowsを入れといてください

 

まずFlutterをGitHubからCloneしてきます

git clone -b alpha https://github.com/flutter/flutter

ブラランチ名から察せる通りまだAlpha版です

これからどう進化していくか楽しみですね

 

次にCloneしたやつのパスを通します

パスが通せたらコマンドプロンプトだかPowerShellだかで

flutter

と打つとなんかやってくれます

以下はPowerShellでやった結果

f:id:bigbuddha:20171218230450p:plain

f:id:bigbuddha:20171218230455p:plain

 

続いて以下のコマンドで開発環境が整っているか確認します

flutter doctor

f:id:bigbuddha:20171218230501p:plain

ちゃんとAndroidStudioが認識されてますね

IntelliJのほうでプラグインが入ってね~ぞと言われていますので

言われた通り導入します

しかし、今回我々が利用するのはAndroidStudioなので

AndroidStudioにプラグインをインストールします

皆さん御存知の通りAndroidStudioはGoogleIntelliJ魔改造して

世に送り出している代物ですので

当然IntelliJ用のプラグインがインストールできます

 

最初にDart用のPluginをインストールしまして

続いてFlutter用のPluginをインストールします

検索しても出てこねぇって人はしたの方にある

「Browse Repositories」ってところをクリックして検索すると出てきます

f:id:bigbuddha:20171218231329p:plain

 

これで無事開発環境が出来上がりました

一度AndroidStudioを再起動させて

ホーム画面を見るとこんな感じになってます

f:id:bigbuddha:20171218231818p:plain

なんとFlutter用の新規ボタンができるんですね~

公式サイトより

> Android Studio, version 3.0 or later.

とのことなんでversion 3からFlutterが公式対応してます

 

みんな大好きHelloWorld

ではプログラマの母であるHelloWorldアプリを作ってみましょう

「Start a new Flutter project」から

適当にWizardに答えていくと無事プロジェクトが作成されます

f:id:bigbuddha:20171218232145p:plain

この状態で「Run」してみましょう

カウンターアプリが立ち上がります

とりあえずはこのコードを読んで雰囲気を掴んでみましょう

レイアウトはこう書くんだな~とか

StatefulってのとStatelessってのがあるんだな~とか

他にも沢山の有益な情報が得られるでしょう

文字列の部分は恐れずにバンバン変えていただいて

どの命令がどんな役割をしているかを感じ取ってください

 

感じきったところでコードを超シンプルにします

以下のコードを

import 'package:flutter/material.dart';

void main() {
  runApp(
    new Center(
      child: new Text(
        'Hello, world!',
        textDirection: TextDirection.ltr,
      ),
    ),
  );
}

実行すると割とオサレなHelloWorldが(左上のメーターは無関係)

f:id:bigbuddha:20171219202410j:plain

無事HelloWorldができたので、なんか一個アプリを作ってみましょう

 

カウンターをRemakeする

新規プロジェクトで表示されるサンプルコード的な何かはカウンターでした

あれを一から順番に作っていきます

以下のページを参考にしています

Building Beautiful UIs with Flutter

A Tour of the Flutter Widget Framework - Flutter

公式はやっぱり最強

 

AppBarを作る

基本的にFlutterは自分でWidget(泥で言うViewぽいもの)を作って

それを画面にポンポンのせるって感じでやっていきます

とりあえず標準のものを使ってぽいものを作ってみる

以下main.dart


import 'package:flutter/material.dart';

void main() {
  runApp(
    new MaterialApp(
      title: "Counter",
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Counter"),
        ),
      ),
    ),
  );
}

 結果がこちら

f:id:bigbuddha:20171219204655j:plain

大体どうしていけばいいか想像がついてきますね

ScaffoldとAppBarをそれぞれ継承したクラスを作成します

 

MyAppBar.dart

import 'package:flutter/material.dart';
import 'package:hello_world/MyAppBar.dart';

class MyScaffold extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // Material is a conceptual piece of paper on which the UI appears.
    return new Material(
      // Column is a vertical, linear layout.
      child: new Column(
        children: <Widget>[
          new MyAppBar(
            title: new Text(
              'Counter',
              style: Theme.of(context).primaryTextTheme.title,
            ),
          ),
          new Expanded(
            child: new Center(
              child: new Text('Hello, world!'),
            ),
          ),
        ],
      ),
    );
  }

}

 

MyScaffold.dart

import 'package:flutter/material.dart';
import 'package:hello_world/MyAppBar.dart';

class MyScaffold extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // Material is a conceptual piece of paper on which the UI appears.
    return new Material(
      // Column is a vertical, linear layout.
      child: new Column(
        children: <widget>[
          new MyAppBar(
            title: new Text(
              'Counter',
              style: Theme.of(context).primaryTextTheme.title,
            ),
          ),
          new Expanded(
            child: new Center(
              child: new Text('Hello, world!'),
            ),
          ),
        ],
      ),
    );
  }

}

そしてmain.dartを以下のように書き換える

import 'package:flutter/material.dart';
import 'package:hello_world/MyScaffold.dart';

void main() {
  runApp(
      new MaterialApp(
          title: "Counter",
          home: new MyScaffold()
      ),
  );
}

 実行すると大体予想通りのものが出来上がる

f:id:bigbuddha:20171219211431j:plain

 

StatelessとStateful

MyAppBarクラスを見るとStatelessWidgetというクラスを継承しているのがわかる

WidgetにはStatelessWidgetとStatefulWidgetの2種類がある

単語の通り、StatelessWidgetはState(状態)の変更がない所謂静的なWidget

StatefulWidgetは動的なWidgetを作る時に継承する

Appbarは当然静的なわけだからStatelessWidgetを継承している

StatefulWidgetは例えば「チャットアプリのメッセージを表示するところ」などがあげられる

今回の場合、カウントしている数字の部分は変動するのでStatefulWidgetを継承したものを使う

 

本体部分

ここから一気に書き上げる

各コードの説明は特にしない

(読むだけでだいたい分かるから)

変数またはクラス名の前に_がついていたら

それはPrivateなものということになります

CounterScreen.dart

import 'package:flutter/material.dart';

class CounterScreen extends StatefulWidget {

  @override
  State&lt;StatefulWidget&gt; createState() =&gt; new _CounterState();
}

class _CounterState extends State&lt;CounterScreen&gt; {

  int _count = 0;

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Container(
      margin: const EdgeInsets.symmetric(horizontal: 8.0),
        child: new Center(
          child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: &lt;Widget&gt;[
            new IconButton(
                onPressed: _increment,
                icon: new Icon(Icons.exposure_plus_1)
            ),
            new Text('$_count'),
            new IconButton(
                onPressed: _decrement,
                icon: new Icon(Icons.exposure_neg_1)
            ),
          ],
        ),
      )
    );
  }

  void _increment() =&gt; setState( () { _count++;} );
  void _decrement() =&gt; setState( () { _count--;} );
}

 結果が以下

f:id:bigbuddha:20171219224235g:plain

 

以上で超雑なFlutterのお触り説明を終わります

しょうもない記事でしたが

もし意見などありましたらどんどんコメントください

(ここはこう書くべきだろとかいう訂正コメント待ってます)