🤔

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

2021/03/10に公開

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

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 の違い 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