Flutter: 標準ウィジェットをコピーして改造する

flutter.ioより 突然ですがFlutterは面白いですよ! クロスプラットフォーム開発ファンとして最近の一押しです。 12/5 Flutter Live ’18 で 1.0.0 が発表されました🎊 そこでFlutterでちょっとアドベントカレンダー記事を書いてみます。 はじめに モバイルアプリ開発においては、画面上にはボタンやツールバーなど様々なUIウィジェットを配置します。 iOS/AndroidのSDKも標準で豊富なUIウィジェットを持っていますが、それらを「少しだけカスタマイズしたい」という事がよくあります。このような… 代理店で仕事をしていて、作成したすべてのアプリを同じように見せることはできないものです。私は彼らに独特の表情を見せて、スタイリッシュなタッチを加える必要があります。 引用: 【翻訳記事】Flutterでのアプリ開発を楽しくさせる4つの方法 - Qiita 引用させていただいた記事では サブクラスを作り、それを自分でデザインします。 という方法が紹介されていますが、そんなに大きく変更したいわけではないが元のウィジェットがサブクラスで一部分だけ変更することが出来ず、かといって全てを自作したり上書きするもの大変すぎる、という事があります。 幸いにしてFlutterは全てのウィジェットのソースコードが公開されているので、それを「コピーして改造する」という方法が使えます。 Android開発においても同様の事はたまに行われるようですが、普段iOS開発をしている身からするとなんと素晴らしく…うらやましい…UI○○のここ変えられないんかよ… ☕ …さて、それでは実際に標準ウィジェット、今回はScrollbarウィジェットをコピーして改造してみようと思います。 なお、検証に使用したFlutter SDKのバージョンは以下(執筆時のmaster)となります。 Flutter 0.11.14-pre.1 • channel master • https://github.com/flutter/flutter.git Engine • revision 7375a0f414 Tools • Dart 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297) やってみる 題材として、まず100件のリスト表示を行うアプリmyappを作ります。 import ‘package:flutter/material.dart’; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(), body: Scrollbar( child: ListView.builder( itemCount: 100, itemBuilder: (BuildContext context, int index) { return ListTile(title: Text(‘$index’)); }, ), ), ), ); } } 見事完成しました!🎊🎉 …が、ここで「スタイリッシュなタッチを加える」べく、スクロールバーの太さを3倍にしなければならなくなった、とします 😰 まずはScrollbarウィジェットに太さを設定する方法がないか調べますが、どうも見つかりません。 そこで サブクラスを作り、それを自分でデザインします。 を実践してみようとしますが、こちら試してみるとわかるのですがScrollbarウィジェットはサブクラスでデザインを変更するのに向かない作りをしています(詳細は割愛)。 こうなると全てを自分で作るか、細かな設定が可能なライブラリが無いかpub を探し回り良さそうなものにスクロールバーを置き換えるか…というところですが、なんとかScrollbarウィジェットのままカスタマイズする方法はないものか。 ここで、先程サブクラスでのデザイン変更を試すべくScrollbarウィジェットの実装ファイル scrollbar.dart を確認している時に、ものすごくそれらしい定数 _kScrollbarThickness を見かけていることを思い出します。 この値はサブクラスでオーバーライドできるような性質のものではありませんが、この値を書き換える事が出来れば…? ということで、Scrollbarウィジェットを直接改造すべく scrollbar.dart Flutter SDKのディレクトリ内からコピーしてきて、プロジェクトの中に取り込んでみます。が、 エラーがあるようです。何が起きているのか見てみると どうやらFlutter SDKの中にいた時は theme.dart から import出来ていた Theme クラスがimport出来ていないようです。 また、どうもこの theme.dart はアプリのプロジェクトからは直接読み込めない様子。 そこで、 Theme クラスのリファレンスを確認すると Flutter > material > Theme と、Theme は material に含まれていそうなので material を確認してみます。 import package:flutter/material.dart のようなので、これに書き換えてみます。 うまくいきました ☺ また、実は material.dart をimportすると widgets.dart もimportされた事になるため import ‘package:flutter/widgets.dart’; は削除することができます。 これで手元にエラーのない scrollbar.dart のコピーが取れたので、はりきって _kScrollbarThickness の値を3倍の18.0に書き換え、あとは読み込んで使うだけです… おっとエラーです、SDK側の Scrollbar と重複してしまいました。どうしよう。 案その1として、手元の scrollbar.dart のスクロールバー実装のクラス名を別のものにする手がありますが、Flutterの開発言語Dartではprefix付きのimport、が出来ます。 as custom としてimportすることで、手元の scrollbar.dart から公開されるScrollbarウィジェットは custom.Scrollbar として標準のものと別に扱うことが出来ます。 他にもDartではimportされるものの一部のみを見せたり逆に一部を隠す事も出来るため、今回の例では import ‘package:flutter/material.dart’ hide Scrollbar; として標準のScrollbarを隠す、という方法もあります。 詳しくはコチラ: Language Tour | Dart さて、ついにカスタマイズしたScrollbarウィジェットを使うことが出来たようです…? 太さが3倍になりました … Continue reading Flutter: 標準ウィジェットをコピーして改造する