はじめに
Livesense Advent Calendar8日目を担当します @Soma-Kato です。普段は転職やバイトのAndroidアプリの開発・運用を担当しています。
今回は社外でやっているFlutterアプリ開発で、Androidではこのライブラリ・APIを使うけどFlutterでは何を使うの?みたいなことが度々あったので、それらを解決したライブラリを紹介したいと思います。
本記事内ではKotlin/Javaで開発されたAndroidアプリをAndroidネイティブ
と記述しています。
View系
flutter_speed_dial
タップすると複数のボタンが出てくるFABです。Googleカレンダーなどでよく使われているタップすると展開するFABですね。
Androidネイティブで実装するには少し面倒ですが、Flutterではflutter_speed_dialという便利なライブラリがあります。
導入方法は以下の通りです。
dependencies:
flutter_speed_dial: ^1.2.5
- FlutterでMDCのFABを扱うのと同様に、
Scaffold
のfloatingActionButton
引数にSpeedDial
Widgetを渡すと、画面右下にFABが表示されます。 -
SpeedDial
のanimatedIcon
引数にAnimatedIconsを渡すと、トップレベルのFABのアイコンを定義できます。 -
children
引数にSpeedDialChild
Widgetを渡すと展開されるFABのレイアウトやタップ時の挙動を定義できます。
return Scaffold(
floatingActionButton: SpeedDial(
animatedIcon: AnimatedIcons.menu_close,
animatedIconTheme: IconThemeData(size: 22.0),
visible: _dialVisible,
children: [
SpeedDialChild(
child: Icon(Icons.accessibility),
backgroundColor: Colors.red,
label: 'First',
onTap: () => print('FIRST CHILD')),
SpeedDialChild(
child: Icon(Icons.brush),
backgroundColor: Colors.blue,
label: 'Second',
onTap: () => print('SECOND CHILD')),
],
),
);
flutter_svg
Androidネイティブ開発ではデザイナーさんに書き出してもらったSVGファイルをAndroidStudioのVector Assetで読み込んで、xmlにしてそれを参照していると思うのですが、Flutterにはその機能はありません。
しかしFlutterではflutter_svgという、SVGを直接読み込めるライブラリがあります。
導入方法は以下の通りです。
assets/
を定義することにより、assets/
配下のSVGファイルをコードから参照できるようになります
dependencies:
flutter_svg: ^0.18.0
flutter:
assets:
- assets/
SvgPicture.asset
でファイル名を渡してあげると、SVGを描画できます。
SvgPicture
自体はStatefulWidget
なので、1つ前のセクションでお話ししたFABのアイコンなどにも使うことができます。
SvgPicture.asset('assets/icon.svg')
scrollable_positioned_list
Flutter標準で実装されているListView
Widgetは優秀ですが、AndroidネイティブのRecyclerViewのようにListのpositionを指定して自動でスクロールされる機能はありません。(scrollToPositionのようなメソッドがありません。)
それを実現できるWidgetを提供しているライブラリがscrollable_positioned_listです。
導入方法は以下の通りです。
dependencies:
scrollable_positioned_list: ^0.1.8
final itemScrollController = ItemScrollController();
final itemPositionsListener = ItemPositionsListener.create();
ScrollablePositionedList.builder(
itemCount: 20,
itemBuilder: (context, index) => Text('Item $index'),
itemScrollController: itemScrollController,
itemPositionsListener: itemPositionsListener,
);
builder自体はListViewとほとんど変わらないのですが、ItemScrollController
とItemPositionsListener
を引数に渡すことができます。
ItemScrollController
のjumpTo(index)
がRecyclerViewのscrollToPosition
と似たような振舞をします。
itemScrollController.jumpTo(index: 10);
keyboard_avoider
AndroidネイティブだとTextField
をタップしてIMEが表示された時に、タップしたTextField
がIMEに隠れないように自動でViewを押し上げてくれると思いますが、Flutterではそのような機能がありません。
それを実現できるWidgetを提供しているライブラリがkeyboard_avoiderです。
導入方法は以下の通りです。
dependencies:
keyboard_avoider: ^0.1.2
autoScroll
引数にtrue
を渡すと、child
引数に定義されている、TextField
がIMEに隠れないように自動でスクロールしてくれます。
KeyboardAvoider(
autoScroll: true,
child: Column(
children: [
TextFormField(),
Container(height: 500),
TextFormField(),
],
),
);
Utility系
json_serializable
Androidネイティブ開発で、APIのレスポンスをPOJOへ変換するためにGsonなどを使うことがあると思います。
Flutterではこのような時に、json_serializableライブラリを使い、Dartクラスへ変換します。
導入方法は以下の通りです。
dependencies:
json_annotation: 3.0.1
dev_dependencies:
json_serializable: 3.3.0
part 'Person.g.dart';
@JsonSerializable()
class Person {
final String firstName;
final String lastName;
Person({this.firstName, this.lastName});
}
Personクラスに@JsonSerializable
をつけ、flutter packages pub run build_runner build
をターミナルなどのコマンドラインで実行すると、MapからPersonへ変換する_$PersonFromJson
と、PersonからMapへ変換する_$PersonToJson
を自動生成してくれます。
part of 'Person.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Person _$PersonFromJson(Map<String, dynamic> json) {
return Person(
firstName: json['firstName'] as String,
lastName: json['lastName'] as String,
);
}
Map<String, dynamic> _$PersonToJson(Person instance) => <String, dynamic>{
'firstName': instance.firstName,
'lastName': instance.lastName,
};
これを先ほど定義したPersonクラスのfactoryコンストラクタなどに記述してあげると、APIレスポンスをDartクラスへ変換できるようになります。
_$PersonToJson
を呼び出せば、PersonクラスをMap<String, dynamic>
へ変換できるので、APIにpostしたり、sqfliteを使ってアプリ内DBに保存したりできます。
...
factory Person.fromJson(Map<String, dynamic> json) =>
_$PersonFromJson(json);
Map<String, dynamic> toJson() => _$PersonToJson(this);
また、Gsonの@SerializedName
のように、@JsonKey
を使いKey名を変更することもできます。
class Person {
@JsonKey(name: "first_name")
final String firstName;
@JsonKey(name: "last_name")
final String lastName;
tuple
Kotlinで関数から複数の値を返したい時などに、PairやTripleを使うと思いますが、Dartはそのようなクラスが実装されていません。
それを実現できるクラスを提供しているライブラリがtupleです。
導入方法は以下の通りです。
dependencies:
tuple: ^1.0.3
実装はとても簡単で、2つの値を持たせたい場合はTuple2
を使い値を渡します。
取り出す時はitem1, item2
を呼び出し値を取り出します。
Tuple2〜Tuple7
まであるので、最大で7つの値を定義することがきます。
Tuple2<int, String> tuple2 = Tuple2(0, "1");
int number = tuple2.item1;
String name = tuple2.item2;
shared_preferences
名前の通りAndroidネイティブ開発でおなじみのSharedPreferencesです。Flutterでは標準で実装されていないので、shared_preferencesライブラリを使うことになります。
導入方法は以下の通りです
dependencies:
shared_preferences: 0.5.10
実装自体はAndroidネイティブのSharedPreferencesとほとんど同じですが、値をセットする時の戻り値がFuture<void>
になるので、非同期処理が必要になります。そういう点で言うと、AndroidXのPreferencesDataStoreに近い感じになっています。
SharedPreferences prefs = await SharedPreferences.getInstance();
int counter = (prefs.getInt('counter') ?? 0) + 1;
print('Pressed $counter times.');
await prefs.setInt('counter', counter);
デバック系
flutter_stetho
AndroidネイティブにもあるStethoライブラリです。
NetworkInspectorやDatabaseInspectorなどが利用できます。
Stethoを使ったことがある人はご存知だと思いますが、AndroidStudio4.1から実装されているDatabaseInspectorとは違い、StethoはDatabaseのテーブルに直接変更を加えることができません。あくまで参照するくらいしかできません。
なので個人的にはちょっと不便だなと思っていますが、FlutterでDatabaseInspector機能があるライブラリが他にない(知らない)ので利用しています。
導入方法は以下の通りです
dependencies:
flutter_stetho: ^0.5.2
main関数内で初期化をし、chrome://inspect
を開けば、いつものStethoの画面を開くことができます。
void main() {
Stetho.initialize();
runApp(new MyApp());
}
alice
Androidネイティブ開発でよく使われるNetworkInspectorのChuckと同じようなことができるライブラリです。
StethoはChromeブラウザで開きますが、aliceはアプリ内で通信ログを確認できるのでとても便利です。
導入方法は以下の通りです
dependencies:
alice: ^0.1.6
実装は少し長いので省略しますが、Exampleを見ていただければ導入できると思います。
まとめ
今回はAndroidではこのライブラリ・APIを使うけどFlutterでは何を使うの?を中心としたライブラリ紹介をさせていただきました。
個人的にFlutterのライブラリは、AndroidやiOSのネイティブ開発に触発されたものが多くあるように感じています。なので、大体必要なものは揃っていると思います。
弊社内でもFlutterを導入するタイミングを見計っています
参考・画像参照
- https://pub.dev/packages/flutter_speed_dial
- https://pub.dev/packages/flutter_svg
- https://pub.dev/packages/scrollable_positioned_list
- https://pub.dev/packages/keyboard_avoider
- https://pub.dev/packages/json_serializable
- https://pub.dev/packages/tuple
- https://pub.dev/packages/shared_preferences
- https://pub.dev/packages/flutter_stetho
- https://pub.dev/packages/alice