Flutterに入門してつまったところ。電卓アプリを作りながら。その１

最近、やっとFlutterに入門。。

こんな電卓アプリを作りながら、Flutterのことを理解している最中。
その際に、悩んだ点や調べた内容の備忘録。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">とりあえず、ボタンを押すと、<br>上の絵が変わるところまでできた(*´ω｀*) <a href="https://t.co/Ty8npyo3eO">pic.twitter.com/Ty8npyo3eO</a></p>&mdash; 積読ハウマッチ📚きらぷか (@kira_puka) <a href="https://twitter.com/kira_puka/status/1191079119695466497?ref_src=twsrc%5Etfw">November 3, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

以下の記事の続き的な内容。
1. [Flutterに入門する前に集めたリンク集 - くらげになりたい。](https://www.memory-lovers.blog/entry/2019/11/01/070000)
2. [Flutterに入門して疑問に思ったことと、そのとき調べたこと - くらげになりたい。](https://www.memory-lovers.blog/entry/2019/11/02/080000)

#### 背景画像をつけたい

Containerのdecorationを使うといける

```dart
class Background extends StatelessWidget {
  Background({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        image: DecorationImage(
            image: AssetImage("images/background.png"), fit: BoxFit.fill),
      ),
    );
  }
}
```

参考: [Flutterで画像背景を設定して透過ヘッダーにする - Qiita](https://qiita.com/nemui-fujiu/items/8c381eca54b35f9350b1)

#### AppBarがないときに、ステータスバーにかぶらないようにしたい

SafeAreaで囲むといけた

```dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: //...,
      ),
    );
  }
```

参考: [SafeArea | Flutter開発する前に知っておきたい35のWidget一覧 - Qiita](https://qiita.com/coka__01/items/dedb569f6357f1b503fd#safearea)

#### HexColorで色を指定したい

標準ライブラリにはないっぽい？
標準クラスをextendsして自作した。

```dart
import 'dart:ui';

class HexColor extends Color {
  static int _getColorFromHex(String hexColor) {
    hexColor = hexColor.toUpperCase().replaceAll("#", "");
    if (hexColor.length == 6) {
      hexColor = "FF" + hexColor;
    }
    return int.parse(hexColor, radix: 16);
  }

  HexColor(final String hexColor) : super(_getColorFromHex(hexColor));
}
```

使い方はこんな感じ。

```dart
import './HexColor.dart';
class ColorText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(
      "123456789",
      style: TextStyle(
        color: HexColor("#4D4DAC"),
      ),
    );
  }
}
```

参考: [colors — Flutterで16進数のカラー文字列を使用する方法](https://www.it-swarm.net/ja/colors/flutter%E3%81%A716%E9%80%B2%E6%95%B0%E3%81%AE%E3%82%AB%E3%83%A9%E3%83%BC%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/838917297/)


#### ImageButtonみたいに、画像にクリックイベントをつける

ImageをGestureDetectorで囲むと、イベントを取得できるっぽい。

```dart
return GestureDetector(
  onTap: () => debugPrint("onTap"),
  child: Image.asset("image/button.png"),
);
```

参考: [Create a button with an image in Flutter? - Stack Overflow](https://stackoverflow.com/questions/53641053/create-a-button-with-an-image-in-flutter/53641444)
参考: [How to add on click event to Image in Flutter](https://inducesmile.com/google-flutter/how-to-add-on-click-event-to-image-in-flutter/)

#### コンソールログを表示する
いろいろ書き方があるっぽい。

```dart
// stderr.writeln
stderr.writeln('print me');

// print, debugPrint
print("print messaage");
debugPrint("debugPrint messaage");

// developer.log
developer.log('log me', name: 'my.app.category');

developer.log('log me 1', name: 'my.other.category');
developer.log('log me 2', name: 'my.other.category');

// developer.log + error
developer.log(
  'log me',
  name: 'my.app.category',
  error: jsonEncode(myCustomObject),
);
```

参考: [Debugging Flutter apps programmatically - Flutter](https://flutter.dev/docs/testing/code-debugging#logging)
参考: [Flutter で print 出力を得たい - Qiita](https://qiita.com/kappaLab/items/602fcdaaa076efa59c3b)

#### Widgetのツリー構造を確認したい

Dev ToolのWidget Inspectionを使う。
Androidの[Layout Inspector](https://developer.android.com/studio/debug/layout-inspector?hl=ja)みたいなやつ。

![Dev Tool](https://flutter.dev/assets/tools/devtools/inspector-3e6fa95156e6a794c715af44e0a85e45609c710f3fe20a24dfac5002fa8d58e0.gif)

参考: [Debugging Flutter apps - Flutter](https://flutter.dev/docs/testing/debugging#devtools)


#### HotReloadが効かない(buildしても再生成されない書き方をしてた)

buildしても再生成されない書き方をしてた...

だめな例。

```dart
class _PageState extends State<Page> {
  Widget _widget = Text("aaaa"); // ←だめなところ

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _widget,
    );
  }
}
```

良い例。

```dart
class _PageState extends State<Page> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text("aaaa"),
    );
  }
}
```

##### 追記

つぶやいたら、monoさんから詳細を教えてもらえた(*´ω｀*)
一連のリプの解説にもある通り、`const`をつけないと、~~キャッシュが使われるよう~~Hot Reloadが効かないよう。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">WidgetのキャッシュとHot Reloadが効くか否かの関係はこんな感じ(　´･‿･｀)<a href="https://t.co/fjG2ropgXs">https://t.co/fjG2ropgXs</a> <a href="https://t.co/H4PUhW3v3u">https://t.co/H4PUhW3v3u</a> <a href="https://t.co/kqqBFFvOt1">pic.twitter.com/kqqBFFvOt1</a></p>&mdash; mono 🎯 @自宅 (@_mono) <a href="https://twitter.com/_mono/status/1191115093964021760?ref_src=twsrc%5Etfw">November 3, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

公式ドキュメントではここ([Hot reload - Flutter](https://flutter.dev/docs/development/tools/hot-reload#recent-code-change-is-included-but-app-state-is-excluded))に、monoさんの[別の記事](https://link.medium.com/yO7z0B7PL0)でも解説されている。

#### フォーマッターでいい感じに整形されない

末尾のコンマをつけていないので、いい感じにならないっぽい。
参考記事をみると「**末尾コンマは大事**」と書いてあった。

> <b>Dartの末尾コンマは大事</b>
> Dartの末尾コンマはその有無によってdartfmt結果が変わったりします。
> Using trailing commasに以下の図とともに説明されているように、
> 基本的には末尾に ”,” を入れた方がきれいかつ横幅もコンパクトに整形されます。

参考: [Flutterでの開発をスムーズに行うためのTips集 - Flutter 🇯🇵 - Medium](https://medium.com/flutter-jp/tips-b2487a63a8)

# おわりに

以下の記事、IDEの機能の紹介やリファクタのTipsもたくさんあるので、
開発前に以下の記事に目を通すとだいぶ楽になる。。
- [Flutterでの開発をスムーズに行うためのTips集 - Flutter 🇯🇵 - Medium](https://medium.com/flutter-jp/tips-b2487a63a8)

やっと、UIができた感じなので、すこしずつ作っていく。
また進んだら、「その2」を調べたところをまとめていく予定〜


## こんなのつくってます!!

積読用の読書管理アプリ 『積読ハウマッチ』をリリースしました！
[積読ハウマッチ](https://tsundoku.site)は、Nuxt.js+Firebaseで開発してます!

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/572d4947-f40b-e4dc-1c9c-bc584cd2a66c.png" width="200"/>

もしよかったら、遊んでみてくださいヽ(=´▽`=)ﾉ

要望・感想・アドバイスなどあれば、
公式アカウント([@MemoryLoverz](https://twitter.com/MemoryLoverz))や開発者([@kira_puka](https://twitter.com/kira_puka))まで♪