🤔

FlutterはなぜButtonを一新したのか

6 min read

こんにちはこんばんわ、すぎっと٩( ᐛ )وです。
今日のテーマはボタンです。

Flutter は最近メジャーバージョンが "2" にアップデートされました。そのタイミングで RaisedButton をとうとう deprecated (非推奨) にしました。もともとは Flutter 1.22 で導入された のですが、移行期間扱いだったんですね。これがとうとう、エディタ上で横線を引かれるようになっちゃいました。

こんな警告が出るようになりました。

RaisedButtonはもう使わんと、ElevatedButton使ってや。移行のやり方はドキュメント作っといたしざーっと見といて。Ver.1.26.0-18.0.pre 以降は非推奨にすることにしてん、堪忍な!

GitHub で経緯を追いかけると、Flutter 2 は Flutter 1.26系から出てきた感じになっていたので、時系列はそんな感じですね。ということで、RaisedButtonはもうお終いということですね。

では、本記事ではこのボタンの移行について説明 しません

移行方法については ガイド がありますよって公式がわざわざエラーメッセージでURL貼ってくるくらい親切にアナウンスしていますので、あえて説明する必要はないでしょう。

タイトルの通り、 なぜ についてフォーカスしたいと思います。なお、個人の理解です。

何が非推奨になって何が追加されたのか

RaisedButtonと銘打って話を始めましましたが、他にも deprecated になったボタンがありますので、ここで一旦整理しておこうと思います。下記の図は先程リンクを貼ったマイグレーションガイドからの引用です。

Old Widget Old Theme New Widget New Theme
FlatButton ButtonTheme TextButton TextButtonTheme
RaisedButton ButtonTheme ElevatedButton ElevatedButtonTheme
OutlineButton ButtonTheme OutlinedButton OutlinedButtonTheme

FlatButton・RaisedButton・OutlineButton の 3 つですね。OutlineButton から OutlinedButton っていうところがちょっと目がチカチカしそうですが、"d" が増えました。これを Dの意志を継ぐもの と言います。

これらの基本の見た目はこんな感じです。

以降の説明では、旧Buttonと新Buttonという表現をします。

旧Buttonと新Buttonの違い by Googleの中の人

あらためて Flutter 1.22 のアナウンス記事を見てみましょう。 Medium の記事ですが著者は Google の中の人です。

こんな一文があります。

Existing Flutter buttons look good but can be hard to use, especially when you need custom theming.

Themingあたりが使いにくいと言っていますね。
さらに、

the Material specification has expanded to include new buttons with new styles.

Material Design にちゃんとついていこうぜって言っていますね。

どういうところが使いにくいのでしょうか。

旧Button と 新Button を実装して比較してみよう

さくっと実装してみました。

全然見た目が違いますね。Themeの設定はとてもシンプルなのですが・・・

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

この違いが使いにくいと言っていることの一部なのかもしれないですね!もう少し詳しくみてみましょう。

押し込んだとき

押し込んだ時の旧Buttonのデザインに注目してみました。


↑outlineの書き間違えです

OutlineButton の外周が青色になりましたね・・・。

「押し込む前の状態 + 中央をグレーに塗る」
が押し込みのデザインだと定義したとすると、OutlineButtonはこれに加えて
「外周の色を変える」
が行われていることになります。少し不恰好だなぁという感想です。

同じように新Buttonについても 押し込んだ時 のデザインを見てみましょう。

こちらはすべて、
「押し込む前の状態 + 中央を薄いブルーに塗る」
になっていますね。個人の感想かもしれませんが、こちらの方がしっかり定義された振る舞いのように思います。

続いてダークモードを見てみましょう

ダークモードのとき

おやおやおや??

新ボタンはメインのカラーをブルーで統一してくれていますが、旧ボタンはなんだか荒れていますね。RaisedButton がブルーになりました。FlatButtonにブルーの要素はないですね。OutlineButton は引き続き押し込んだ時の外周がブルーです。

↑outlineの書き間違えです

旧Buttonと新Buttonはテーマの仕組みが変わった!!

結論から言えばそういうことです。Themeの仕組みが変わりました。
マイグレーションガイドの比較表を再度引用します。

Old Widget Old Theme New Widget New Theme
FlatButton ButtonTheme TextButton TextButtonTheme
RaisedButton ButtonTheme ElevatedButton ElevatedButtonTheme
OutlineButton ButtonTheme OutlinedButton OutlinedButtonTheme

旧Button群は ButtonTheme を共通して使用しています。
一方、新Buttonは 各々が専用のThemeを持っています。

実際、ThemeDataの実装を見ると完全に別で保持されていますね。(下記参照)

https://api.flutter.dev/flutter/material/ThemeData/ThemeData.html

ということで、Buttonが一新された理由は 旧Themeシステムじゃ使いにくい でした。

Buttonの次はThemeかよ

はい、そうです。

ThemeSystemはどう変わったのか

詳しい情報が公式からドキュメントとして出ています。ほんと、しっかりしてますね。
Material Theme System Updates

誤解を恐れず言えばこんな感じです。

ThemeDataに足し算であれこれ機能を追加してきたけどコンポーネントに適用されるテーマをうまく切り分けられないのでスタイルの依存関係が把握しずらいし実装はぐちゃぐちゃでメンテしずらいしもう良いことないから新しくする!!大掃除!!でもちゃんとBreakingChangesの適用ルールに従って、事前アナウンスして移行をサポートするよ!安心してね!

このThemeの変更に関するガイドをイチから説明するのは大変なので、Buttonのところだけみてみます。

時間をとって全部読むことをお勧めします。とても学びが多いです。

Buttonに関するところも旧ThemeでButtonThemeオンリーでやっていくのがいかに大変だったのかが書かれています。Themeがうまく機能しないなら結果的に局所的な実装が増えてしまって残念なことになるよね、という感じだと受け取りました。

例として先程あげた3つのボタンでいえば、RaisedButtonは塗りつぶしがあるので、そのテキストの色は他のボタンと同じにはできないですよね。これをコントロールするのはちょっと一手間必要だったんだよ、といったものです。こういう細かい気苦労が他にもいろいろあったようですね。

この気苦労については旧Buttonと新Buttonのプロパティを比べれば一目瞭然かもしれません。

  • 旧Button (RaisedButton)

  • 新Button (ElevatedButton)

超スッキリしましたね。ごちゃごちゃしていた見た目に関するプロパティがすべて ButtonStyle にまとめられました。

この ButtonStyle が何者なのかを掘り下げていくと、MaterialStateProperty に絡んだややこしい話が必要になります。各ボタンのデフォルトのスタイルをどうやって決めているか、みたいなところもみていく感じになります。継承関係の把握も必要です。つまるところ、material パッケージの中身をゴリゴリ解読していく感じですね。これはこれで楽しいのですが、記事が無限に長くなるので適当なところで手を打とうと思います。

ButtonStyle についてはこれが何者かは置いておいて、どういう用途で使うかだけ触れておしまいにしようと思います。

ざっくり言えば、各ボタンのデフォルトのスタイル(MaterialAppのThemeをベースに組まれたスタイル)に対して一部のスタイルを上書きする ために使います。

つまり?

デフォルトが何かちゃんと把握してから書こうね!

ということです。

新しいボタンはこうやって書くらしいよ! なんかよくわかんないけど!

こういうのはやめましょうということです。

せっかくエンジニアやっているので、新しい機能や仕組みが追加された時は 「どうやって使うんだろう・何が変わったんだろう」だけではなくて、「なんで追加したのかな」まで理解したい なぁと思っています。説教臭くなりましたが真意は違います。

ソフトウェアエンジニアって楽しいよね!!
だってスーパーエンジニアたちが作ったソースコード全部読めるんだよ!!
しかもタダだよ!!そんなことある??
(ありがとう、オープンソース)

まとめ

  • 旧ボタンより新ボタンはスタイルの仕組みがちゃんとしているよ
  • その背景にはテーマの仕組みを新しくしたいっていう思惑があったんだよ
  • ソフトウェアエンジニアって楽しいよね
  • OSSありがとう

お付き合いいただきありがとうございました。

すぎっと٩( ᐛ )و

GitHubで編集を提案

Discussion

ログインするとコメントできます