20
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2020-04-27

概要

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

内容

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

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

方法

  • [推奨] leadingWidthを使う
  • OverflowBoxを使う
  • TitleにStackを使う

[2022/02/14追記] leadingWidth

現在は下記のように leadingWidth に適切なサイズを指定してあげるだけで問題ない。
この方法だとタップ領域も正しく反映される。

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を大きくできるよ的な内容だった
下記のような感じ

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のサイズをはみ出した部分(つまりオーバフロー部分)にタップ領域が設定されない。

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
                  ),
                ),
              ),
            ),
          ),
        )

これで下記のような感じにできた。
スクリーンショット 2020-04-27 11.23.43.png

TitleにStackを使う

上記の方法ではleft paddingなどを追加しないといけないため他の方法を考えた。
個人的にはこっちを推奨したい。
[2022/02/14追記] 現在は leadingWidth が設定できるのでそちらを推奨

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

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

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

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
とする。
スクリーンショット 2020-04-27 11.49.32.png

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

まとめ

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

20
17
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?