Flutter小ネタ集① 〜「それ、できますよ?」って言いたくなる瞬間〜
こんにちは@ヒラメです。
エンジニアをしていると、「それ、できますよ?」と言いたくなるような小ネタに出会うことがあります。
この記事では、Flutterを使った開発の中で出会った、そんな小さな実装アイデアや工夫を第一弾としてまとめました。ちょっとした参考やヒントになればうれしいです。
🎢 ListViewで横スクロールをエッジまで自然に見せる工夫
シャドーイングのレッスン情報をカード形式にして、ListView
で横スクロール表示しています。
ポイントは、ファーストビューやスクロールの終端ではパディングを入れ、スクロール中はカードを画面エッジまで表示することです。
ファーストビュー(初期表示)
最初のカードが画面端に張り付かないよう、左側にパディングを設けています。右側はエッジまでしっかり表示されるため、自然なバランスで「スクロールできる感」が伝わります。
スクロール終端
最後のカードが画面端に張り付かないよう、右側にパディングを追加しています。これにより「ここでスクロールが終わり」という余白が自然に生まれます。
ListView(
scrollDirection: Axis.horizontal, // 横スクロール
padding: EdgeInsets.only(right: 16), // 終端までスクロールしたときのパディング
shrinkWrap: true,
children: lessonModel.map((lesson) {
return Padding(
padding: EdgeInsets.only(left: 16), // ファーストビューの左側パディング
child: SizedBox(
width: 234,
child: BoxMasterLesson(
location: DisplayLocation.master,
title: lesson.title,
imagePath: lesson.imagePath,
description: lesson.description,
isLock: lesson.isLock,
wpm: lesson.wpm,
progress: lessonProgress[lesson.docId]?.progress ?? 0,
max: lessonProgress[lesson.docId]?.max ?? 0,
onPressed: () => onPressed.call(lesson.docId),
),
),
);
}).toList(),
)
ファーストビューの左側パディング
各カードを Padding
でラップして左側に余白を入れています。
これにより ListView
自体の横幅はそのままに、最初のカードが画面端に張り付かず自然に表示されます。また、この Padding
はカード同士の間隔にも作用しています。
終端までスクロールしたときのパディング
こちらは ListView
に直接パディングを指定しています。
リスト全体のサイズを変えることなく、最後のカードの右側だけに余白を確保できます。
🎨 リーセントでの帯のカラー for Android
古くからAndroidとのお付き合いのある方ならわかるこのリーセント。Flutterプロジェクトのデフォルトのままだと紫色のままですが、カラーを指定し変更することができます。
return MaterialApp.router(
// テーマの設定
theme: ThemeData(
primaryColor: Colors.green,
),
MaterialApp.router
の theme
に primaryColor
を指定すると反映されます。
ちょっとした調整ですが、プロジェクトの統一感を出すのに役立ちます。
didPush
をゲットする
💬 ダイアログの表示で シャドマスは go_router を使ってルーティングの管理をしています。Firebase Analyticsと連携して遷移情報を分析しているアプリも多いかと思います。ShellRoute
のobservers
にNavigatorObserver
をセットしておけば大半の画面であれば自ずとdidPush
とdidPop
が検知できますが、ダイアログの表示は少し工夫が必要です。
Future<int?> show() {
return showDialog<int>(
context: context,
barrierDismissible: false,
useRootNavigator: useRootNavigator,
routeSettings: RouteSettings(name: name), // ダイアログの名前を設定
builder: (BuildContext context) => HookBuilder(
builder: (context) {
final media = useMediaQuery();
return AlertDialog(
insetPadding: EdgeInsets.symmetric(horizontal: 16),
contentPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
content: SizedBox(
width: media.size.width,
child: child,
),
);
},
),
);
}
showDialog
は内部的に Navigator.push
を使って DialogRoute
を追加しています。そのときに routeSettings
を渡すと、その情報が DialogRoute.settings
に反映されます。NavigatorObserver
は Navigator
に対して新しいルートが push
されたときに必ず通知を受ける仕組みなので、ダイアログが表示された瞬間に didPush
が呼ばれ、そこで RouteSettings.name
が確認できる、という流れになっています。
📌 まとめ
今回紹介したのは、どれも「大きな機能追加」ではなく、UI を自然に見せたり、アナリティクスの計測精度を少し上げたりといった ちょっとした工夫 でした。こうした小さな改善の積み重ねが、アプリ全体の完成度やユーザー体験を大きく変えてくれます。
今後も Flutter 開発の中で見つけた「それ、できますよ?」なアイデアを紹介していくので、ぜひ参考にしてみてください。
🚀 アプリのダウンロードはこちら
🍎 App Store(iOS):
🤖 Google Play(Android):
いくつかのシャドーイングは無料で試せるので、ぜひダウンロードして使ってみてください!
Discussion