codelabでflutterのチュートリアルをした


#本文
###このサイト良い
[codelab](https://flutter.dev/docs/get-started/codelab)

###hot reload便利

#以下メモ
codelabでflutterの勉強をした時のメモ

###参考
[codelab](https://flutter.dev/docs/get-started/codelab)

##プロジェクト作成・実行の流れ

プロジェクト作成

```
$ flutter create my_app
$cd my_app/
```
VSCodeとかで編集後

```
$flutter run
```

シミュレータデバイスが複数ある場合デバイスIDを指定する

```
$flutter run

More than one device connected; please specify a device with the '-d <deviceId>' flag, or use '-d all' to act on all devices.
iPhone SE • hogeID
iPhone Xs • fugaID

$flutter run -d hogeID
```

##Hello World表示
```dart:/lib/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: Text('Welcome to Flutter'),
        ),
        body: Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/e2cf7313-b606-fa0e-e89e-1c578d7381f3.png)

returnで返しているMaterialApp()の中身が画面の要素になってる

##ライブラリの使用

ランダムな単語の組み合わせを生成して表示する

ライブラリをインポート

```yml:/pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
##これ追加
  english_words: ^3.1.0      
```

```dart:/bin/main.dart
import 'package:flutter/material.dart';
// これ追加 importしてライブラリを使えるようにする
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: Text('Welcome to Flutter'),
        ),
        body: Center(
// ここ変更 生成した文字列の表示
          child: Text(wordPair.asPascalCase),
        ),
      ),
    );
  }
}
```
hot reloadすると文字列が変わる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/8076b045-4260-cdf5-8206-e248f90ced6b.png)



##文字出力処理の切り出し

```dart:/bin/main.dart
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: Text('Welcome to Flutter'),
        ),
        body: Center(
// ここ変更
          child: RandomWords(),
        ),
      ),
    );
  }
}


// 以下追加 
class RandomWords extends StatefulWidget {
  @override
  RandomWordsState createState() => RandomWordsState();
}


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

実行結果は同じ


##Listに表示する

tabaleView的なものにランダム生成した文字列を表示する画面を作る。

```dart:/bin/main.dart
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) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

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

class RandomWordsState extends State<RandomWords> {
// _をつけるとprivateになる
  final _suggestions = <WordPair>[];
  final _biggerFont = const TextStyle(fontSize: 18.0);

  @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.0),
        itemBuilder: (context, i) {
// 奇数行なら区切り線を返す
          if (i.isOdd) return Divider();
// 偶数行の場合ランダム生成した単語の組み合わせを返す
          final 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,
      ),
    );
  }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/3410a317-1bfa-99b3-2a21-4c565a62f210.png)


お気に入りボタンを追加

```dart:/bin/main.dart
・
・
・
class RandomWordsState extends State<RandomWords> {
  final List<WordPair> _suggestions = <WordPair>[];
//　追加
  final Set<WordPair> _saved = Set<WordPair>();
  final TextStyle _biggerFont = const TextStyle(fontSize: 18.0);

・
・
・

  Widget _buildRow(WordPair pair) {
    final bool alreadySaved = _saved.contains(pair);
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
// 追加
      trailing: Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),        
    );
  }
}
```

#####hot reload　すると変更が反映される(すごい便利！)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/a15aab7b-fc84-be12-49bb-408ed095b4e0.png)

(VSCodeで行の左にアイコンが表示されたり、色名にカーソルを合わせると色見せてくれるのすごい便利！)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/8030a435-9f0d-3a4d-ea77-4b88a6a22278.png)

##ボタンをインタラクティブにする

```dart:/bin/main.dartt
  Widget _buildRow(WordPair pair) {
    final bool alreadySaved = _saved.contains(pair);
    return ListTile(
      title: Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        // Add 9 lines from here...
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/46bccc65-01c8-dd20-50bb-99e534fe0dfb.png)

##画面遷移

###遷移ボタン追加

```dart
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
// 追加
        actions: <Widget>[
          IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
        ], 
// ここまで        
      ),
      body: _buildSuggestions(),
    );
  }

class RandomWordsState extends State<RandomWords> {
・
・
・

// 画面遷移関数追加
  void _pushSaved() {
  }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/a4d17907-a16e-76ab-d489-128dddb01076.png)


###遷移処理追加

```dart
  void _pushSave() {
    Navigator.of(context).push(
      MaterialPageRoute<void>(
        builder: (BuildContext context) {
// お気に入り登録したリストから表示文字を生成
          final Iterable<ListTile> tiles = _saved.map(
            (WordPair pair) {
              return ListTile(
                title: Text(
                  pair.asPascalCase,
                  style: _biggerFont,
                ),
              );
            },
          );
// 線で区切る
          final List<Widget> divided = ListTile.divideTiles(
            context: context,
            tiles: tiles,
          ).toList();

// 画面の表示定義
          return Scaffold(
            appBar: AppBar(
              title: Text('Saved Suggestions'),
            ),
            body: ListView(children: divided),
          );
        },
      ),
    );
  }
```

遷移できるようになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/6eb49426-01da-1b64-655e-bcb48a4a37f1.png)



##テーマ色を変える

```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
// 追加
      theme: ThemeData(
        primaryColor: Colors.white,
      ),  
// ここまで
      home: RandomWords(),
    );
  }
}
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542614/181ccf18-8bf0-7ae2-dcb2-fb0963ddc40e.png)


##参考
[codelab](https://flutter.dev/docs/get-started/codelab)