AppBarのleadingにテキストボタンを追加したい

# 概要
AppBarを使った際leadingにIconボタン以外のカスタムボタンを置きたかったときにハマったのでメモ

# 内容
AppBarのLeftにIconButtonではなくTextでキャンセルという文字を置きたかった。
しかし、leadingにTextを設定してもDefalutの56pxのWidthが設定されており、意図した通りに表示できなくて困った。
色々調べて解決策は以下

<font color="Red">**[2022/02/14追記]**</font>
現在は `leadingWidth` プロパティが設定できるようになっているので単純に指定の幅を設定してあげれば良い
（@akita3375さん、コメントありがとうございます）

# 方法
- <font color="Red">**[推奨]**</font> leadingWidthを使う
- OverflowBoxを使う
- TitleにStackを使う

## <font color="Red">**[2022/02/14追記]**</font> leadingWidth
現在は下記のように `leadingWidth` に適切なサイズを指定してあげるだけで問題ない。
この方法だとタップ領域も正しく反映される。

```dart
AppBar(
   leadingWidth: 110,  //leadingWidthを設定する
   leading: TextButton(
      child: Text(
         'キャンセル',
         style: TextStyle(
           color: Colors.grey,
           fontSize: 14,
          ),
      ),
  ),
```

## OverflowBox
カスタムアイコン以外に設定しようと調べても出てこない中こんなISSUEを見つけた。
https://github.com/flutter/flutter/issues/21991#issuecomment-441728934

その中でこのようなコメントがあった。
> I too wanted to have a wider Leading widget than the default 56. I wanted to have the word 'Cancel' presented to the user (versus the standard X icon), when using the route as a fullScreenDialog. I was able to work around this 'issue' by wrapping my leading 'Flatbutton' in an OverflowBox, with a maxWidth of 90.0.

つまりFlatButtonをOveerflowBoxで囲むとleadingのWidthを大きくできるよ的な内容だった
下記のような感じ

```dart
appBar: AppBar(
          leading: OverflowBox(
            maxWidth: 110,
            child: FlatButton(
              child: Text(
                "キャンセル",
                style: TextStyle(
                  color: Colors.grey,
                  fontSize: 14
                ),
              ),
            ),
          ),
        )
```
~~しかし、overflowBoxを指定すると中心が変わらずWidthの上限が広がるので、画面から文字がはみだしてしまう。ためContainerでleft paddingをつける必要があった。~~
[6/17] 修正: alignmentを指定することでpaddingは不要になりました。
しかしこの方法でやる場合、もともとのleadingのサイズをはみ出した部分（つまりオーバフロー部分）にタップ領域が設定されない。

```dart
appBar: AppBar(
          leading: Container(
            // padding: EdgeInsets.only(left: 40), <- 不要になったコード
            alignment: FractionalOffset.centerLeft, // <- 追記したコード
            child: OverflowBox(
              maxWidth: 110,
              child: FlatButton(
                child: Text(
                  "キャンセル",
                  style: TextStyle(
                    color: Colors.grey,
                    fontSize: 14
                  ),
                ),
              ),
            ),
          ),
        )
```

これで下記のような感じにできた。
<img width="387" alt="スクリーンショット 2020-04-27 11.23.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104317/81a11a2d-ca4c-d4e3-a7f4-41fc58c2e276.png">

# TitleにStackを使う
上記の方法ではleft paddingなどを追加しないといけないため他の方法を考えた。
~~個人的にはこっちを推奨したい。~~
<font color="Red">**[2022/02/14追記]**</font> 現在は `leadingWidth` が設定できるのでそちらを推奨

`Stack Widget` はFlutterに置いて絶対位置指定などをしたいときに使われる。
Viewを重ねたいときなどに使えるだろう。

今回は `Stack widget` の中で `Align Widget` を使うことで、親のWidgetに対してそれぞれ位置指定を行う。

下記のコードで上記と同じようにViewが作れる。

```dart
title: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Align(
                alignment: Alignment.centerLeft,
                child: ButtonTheme(
                  padding: EdgeInsets.symmetric(vertical: 8),
                  materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                  minWidth: 0,
                  height: 0,
                  child: FlatButton(
                    child: Text(
                      "キャンセル",
                      style: TextStyle(
                        color: Colors.grey,
                        fontSize: 14
                      ),
                    ),
                    onPressed: () {},
                  ),
                ),
              ),
              Align(
                alignment: Alignment.center,
                child: const Text(
                  "タイトル",
                  style: TextStyle(
                    fontSize: 16,
                    color: Colors.black54,
                    fontWeight: FontWeight.bold
                  ),
                ),
              ),
            ],
          ),
          automaticallyImplyLeading: false,
```

`Align Widget` は親Viewに対してalignmentを指定することで配置する場所を決定できる。
今回は
キャンセル: Alignment.centerLeft
タイトル  : Alignment.center
とする。
<img width="791" alt="スクリーンショット 2020-04-27 11.49.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104317/4ef16f41-b469-63b0-b522-99185d8f3b5a.png">

ここでポイントはStack Widget自体のAlignmentを
`alignment: Alignment.center`
と指定することである。
デフォルトではtopStartが設定されているので、上記のようにキャンセル,タイトルを設定してもtopよりの配置になってしまう。

# まとめ
上記のような方法でleadingにIcon以外のボタンを設定することができた。
他に何か良い方法があれば教えていただけると幸いです。