広告 Android Dart Flutter フレームワーク プログラミング

Flutterのドキュメントにそってやってみる

2020年9月27日

ではではやっていきましょう。
いきなり「Flutterでアプリ作るぜ!」と言ってもできないですよね。(できる人もいますが......)
ひとまずは公式のチュートリアルをあさっていきます。
今回の記事はこのサイトの内容に沿って進めていきます。

[st-card-ex url="https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1/#0" target="_blank" rel="nofollow" label="" name="" bgcolor="" color="" readmore=""]

まずはここからやっていきましょう。
あ、ちなみに開発環境はこんな感じです。

  • Windows10 64bit
  • Android Studio

Write your first Flutter app, part 1

「最初のアプリを作っていきましょー」ってところですかね。
1と2は環境のセットアップのようなので3の「Create the starter Flutter app」から始めますね。

Create the starter Flutter app

まずは、Android StudioでFlutterのプロジェクトを作成しておいてください。
前回の記事でその辺は説明しているので併せて見ていただけるとわかると思います。

[st-card-ex url="https://www.dice-programming-etc.com/flutter_app_sample/" target="_blank" rel="nofollow" label="" name="" bgcolor="" color="" readmore=""]

Android Studioでプロジェクトを作成すると、すでに「main.dart」の中に色々と書いてあると思います。
一旦全て削除してしまいましょう。
そうしたらこのページにあるコードをコピペしましょう。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),
        body: const Center(
          child: const Text('Hello World'),
        ),
      ),
    );
  }
}

これを記述したらアプリを立ち上げましょう。

firstApp

おぉー、これだけのコードでここまでできるんですね。これは一通りやればちょっとしたアプリは作れそうですね。下の方に書いてあった説明の日本語訳置いときますね。

この例では、Material アプリを作成します。
Material は、モバイルやウェブで標準的に使用されているビジュアルデザイン言語です。
Flutter には豊富な Material ウィジェットが用意されています。
メインメソッドは矢印 (=>) 記法を使用します。
1行の関数やメソッドには矢印表記を使用します。
アプリは StatelessWidget を拡張しているのでアプリ自体がウィジェットになります。
Flutterでは、整列、パディング、レイアウトなど、ほとんどすべてがウィジェットになっています。
Material ライブラリの Scaffold ウィジェットは、デフォルトのアプリバー、タイトル、ホーム画面のウィジェットツリーを保持する body プロパティを提供します。
ウィジェットのサブツリーは非常に複雑です。
ウィジェットの主な仕事は、他の低レベルのウィジェットの表示方法を説明するビルドメソッドを提供することです。
この例のボディは、テキスト子ウィジェットを含むセンターウィジェットで構成されています。Center ウィジェットは、ウィジェットのサブツリーを画面の中央に配置します。

ほー、アプリ自体がウィジェットという扱いになるんですねー。Flutterはほぼ全てウィジェットとして扱っているみたいですね。(よくわかってない)
とりあえず次に行きましょう。

Use an external package

ほうほう、外部ライブラリを使うようですね。
ここで使われるライブラリは「english_words」と言うよく使われる英単語の数千語といくつかのユーティリティ関数を含むオープンソースのライブラリです。(とのことです。)
次のステップとしてはpubspecファイルに追記していくようです。

pubspecファイルとは

Flutterアプリのアセットを管理するファイル

pubspec.yamlにenglish_words. 3.1.5 ( english_words 3.1.5 以上 ) を依存関係リストに追加します。

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  english_words: ^3.1.5   # これを追加

Android Studioだとpubspec.yamlを開いているとこんな感じに表示されていると思います。

この「Pub get」をクリックするとパッケージがプロジェクトに引き込まれます。

In lib/main.dart, import the new package:

訳:lib/main.dartに、新しいパッケージをインポートしていきます。
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';  // この行を追加

As you type, Android Studio gives you suggestions for libraries to import. It then renders the import string in gray, letting you know that the imported library is unused (so far).
Next, you'll use the english_words package to generate the text instead of using "Hello World".

訳:
入力すると、Android Studioがインポートするライブラリの候補を表示します。
そして、インポートされた文字列が灰色で表示され、インポートされたライブラリが今のところ未使用であることを示してくれます。。
次に、"Hello World" の代わりに english_words パッケージを使ってテキストを生成しましょう。

ほうほう。なるほどね。インポートして「english_words」を使えるようにするってことですね。
パッケージ「english_words」で実行するごとにランダムな英単語を出力していく感じみたいですね。

If the app is running, hot reload to update the running app. (From the command line, you can enter r to hot reload.) Each time you click hot reload or save the project, you should see a different word pair, chosen at random, in the running app. That's because the word pairing is generated inside the build method, which runs each time the MaterialApp requires rendering, or when toggling the Platform in the Flutter Inspector.

訳:
アプリが実行中の場合は、ホットリロードして実行中のアプリを更新します。
ホットリロードをクリックするか、プロジェクトを保存するたびに、実行中のアプリにランダムに選択された異なる単語のペアが表示されるはずです。
これは、単語のペアリングがビルドメソッドの中で生成されるためです。

ホットリロードや、保存をすることで文字列が変化していくようですね。
実行した結果がこちら。

1回目
2回目

おー、変わっていますね。次行ってみよー。
コードはこちら。

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final wordPair = WordPair.random(); // この行を追加
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),
        body:Center(
          //child: const Text('Hello World'),
          child: Text(wordPair.asPascalCase),
        ),
      ),
    );
  }
}

Add a stateful widget

ステートフルウィジェットの追加とのことで......、このステップではステートフルウィジェットのRandomWordsを追加するみたいですね。
追加するのはMyAppクラスの下ですね。末尾にこれを追加しましょう。

class RandomWordsState extends State<RandomWords> {

}

はい。で、この時点ではエラーが出ていますがこれから追加していくプログラムで解消されるのでご安心を。次にStatefulWidgetを継承したRandomWordsクラスを作成します。

class RandomWords extends StatefulWidget {
  @override
  RandomWordsState createState() => new RandomWordsState();
}

次はRandomWordsStateクラスにbuildメソッドを追加します。widgetを構築するやつですかね。

class RandomWordsState extends State<RandomWords> {
  @override
  Widget build(BuildContext context) {
    final wordPair = WordPair.random();
    return Text(wordPair.asPascalCase);
  }
}

次は......、MyAppを少し修正するみたいです。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final wordPair = WordPair.random();  // この行は削除

    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: Center(
          //child: const Text('Hello World'),   // コメントアウト
          //child: Text(wordPair.asPascalCase), // コメントアウト 
          child: RandomWords(),                 // この行を追加
        ),
      ),
    );
  }
}

はい、終わりました。
正直に言います!見た目は一切変わりません!はい。このステップは以上!

Create an infinite scrolling ListView

このステップでは、RandomWordsStateを使って単語のリストを生成して表示するみたいです。
ユーザーがスクロールすると、は無限に生成されていくリスト(ListViewウィジェットに表示される)を実装していくみたいです。ListViewのビルダーファクトリのコンストラクタを使用すると、必要に応じてリストビューを簡単に構築することができるそうです。

まずはRandomWordStateクラスに状態変数を追加していきましょう。

class RandomWordsState extends State<RandomWords> {
  final List<WordPair> _suggestions = <WordPair>[];            // NEW
  final TextStyle _biggerFont = const TextStyle(fontSize: 18); // NEW
......

提案された単語の組み合わせを保存するための _suggestions list を追加しました。
また、フォントサイズを大きくするための _biggerFont 変数を追加しています。

次に、RandomWordsStateクラスに_buildSuggestions()関数を追加していきます。
このメソッドは、提案された単語を表示するListViewを構築します。

  Widget _buildSuggestions() {
    return ListView.builder(
      padding: const EdgeInsets.all(16),.
      itemBuilder: (BuildContext _context, int i) { //※1
        if (i.isOdd) {
          return Divider(); //※2
        }
        final int index = i ~/ 2; //※3
        if (index >= _suggestions.length) {
          _suggestions.addAll(generateWordPairs().take(10)); //※4
        }
        return _buildRow(_suggestions[index]); //※5
      }
    );
  }

※1.itemBuilderで一行ごとに処理が呼ばれ、偶数行の場合にListTileを表示し、奇数行のときにDividerを表示します。
※2. 1ピクセルの高さの仕切りをListViewに追加します。
※3.行数を2で割ったときの整数値を求めます。
※4.保存されている英文リスト数を超えた場合は、さらに10個の英文を生成しリストに追加します。
※5.最後に現在の行で表示する英文をリストから取得し、_buildRowメソッドで表示用に整形しています。
次に、_buildRowメソッドの追加します。

  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }

RandomWordsStateクラスのbuildメソッドを書き換え、_buildSuggestionsメソッドを呼び出すように変更します。AppBarの定義も移しちゃいましょう。MyAppクラスで定義していたヘッダーも移動させてしまいます。

......
class RandomWordsState extends State<RandomWords> {
  final List<WordPair> _suggestions = <WordPair>[];            // NEW
  final TextStyle _biggerFont = const TextStyle(fontSize: 18); // NEW
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }
......

MyAppクラスを少し変更しましょう。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: RandomWords(),
    );
  }
}

これでOK!では実行してみましょう。おそらくスクロールし続けても永遠にリストが続くと思います。

完成したプログラムを置いておきます。

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final wordPair = WordPair.random();  // この行は削除

    return MaterialApp(
      title: 'Welcome to Flutter',
      home: RandomWords(),
    );
  }
}

class RandomWordsState extends State<RandomWords> {
  final List<WordPair> _suggestions = <WordPair>[];            // NEW
  final TextStyle _biggerFont = const TextStyle(fontSize: 18); // NEW
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );
  }
  Widget _buildSuggestions() {
    return ListView.builder(
        padding: const EdgeInsets.all(16),
        itemBuilder: (BuildContext _context, int i) {
          if (i.isOdd) {
            return Divider();
          }

          final int index = i ~/ 2;
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10));
          }
          return _buildRow(_suggestions[index]);
        }
    );
  }
  Widget _buildRow(WordPair pair) {
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  RandomWordsState createState() => new RandomWordsState();
}

これで今回のチュートリアルは終わりになります。

まとめ

はい、お疲れ様でした。チュートリアルということもあって簡単でしたね。JavaやKotlinでAndroidアプリケーションを開発したことのある人には若干違和感があったかもしれませんね。
私は少し違和感を感じつつ、「あ、これは分かるようになると結構作りやすいぞ」と思っていました。
今回は英語のチュートリアルを見てプログラミングを行っていましたが、日本語訳をしているサイトもあるようです。お好きな方を見て練習すると良いと思います。
では、今回はここまでになります。今後もチュートリアルに触れつつ、オリジナルのアプリケーションを作っていこうと思います。
次回の記事をお待ちください。

日本語チュートリアル

[st-card-ex url="https://flutter.ctrnost.com/tutorial/" target="_blank" rel="nofollow" label="" name="" bgcolor="" color="" readmore=""]

-Android, Dart, Flutter, フレームワーク, プログラミング
-