Flutter Android アプリでリップルエフェクトが画面遷移時に一時停止する問題
問題の発見
Flutter でAndroidアプリを開発している際、InkWell
を利用したウィジェットからのPush遷移時に、タップしたウィジェットのリップルエフェクトが途中で一時停止する問題に遭遇しました。
この現象はInkWell
だけでなく、ElevatedButton
やFilledButton
などのMaterialコンポーネント全般で発生していました。
具体的な動作は以下の通りです。
- Material系ウィジェットをタップ
- リップルアニメーションが開始
-
Navigator.push
による画面遷移が発生 - リップルアニメーションが途中で停止
- 遷移先から戻ると、停止していたアニメーションが再開
画面遷移後に戻ると、リップルエフェクトが再開される
開発環境情報
執筆時点での環境情報は以下の通りです。
$ fvm flutter doctor -v
[✓] Flutter (Channel stable, 3.32.0, on macOS 15.4.1 24E263 darwin-arm64, locale ja-JP)
• Flutter version 3.32.0 on channel stable
• Framework revision be698c48a6 (2025-05-19)
• Engine revision 1881800949
• Dart version 3.8.0
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
• Platform android-35, build-tools 35.0.0
• Java version OpenJDK Runtime Environment Temurin-17.0.13+11
原因の調査
調査の結果、MaterialPageRoute
のallowSnapshotting
プロパティが原因であることが判明しました。
allowSnapshotting
(デフォルト:true
)は、画面遷移時に現在のウィジェットツリーの静的なスナップショットを作成し、遷移アニメーション中にそのスナップショットを表示する機能です。これにより遷移中のパフォーマンスは向上しますが、進行中のアニメーション(リップルエフェクト、ProgressIndicator
など)は一時停止されます。
解決方法
MaterialAppのテーマ設定でスナップショット機能を無効化
PageTransitionsTheme
でallowEnterRouteSnapshotting
を無効化します。
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
+ pageTransitionsTheme: const PageTransitionsTheme(
+ builders: <TargetPlatform, PageTransitionsBuilder>{
+ TargetPlatform.android: ZoomPageTransitionsBuilder(
+ allowEnterRouteSnapshotting: false,
+ ),
+ },
+ ),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
なお、特定のルートでのみ対応したい場合は、以下のように設定することも可能です。
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const NextPage(),
allowSnapshotting: false,
),
);
画面遷移後に戻っても、リップルエフェクトは再開せず停止したまま
なお、この問題はAndroid特有の現象です。iOSでは異なる遷移メカニズムを使用しているため発生しません。
プラットフォーム別の遷移方式
- Android: ZoomPageTransitionsBuilder(ズーム効果 + スナップショット機能)
- iOS: CupertinoPageTransitionsBuilder(スライド遷移 + ライブレンダリング)
技術的な詳細
Android遷移の仕組み
AndroidではAndroid 10(API レベル29)以降、ZoomPageTransitionsBuilder
が採用されています。この遷移方式では、パフォーマンス向上のためallowSnapshotting
機能(デフォルト有効)により、遷移開始時にウィジェットツリーの静的スナップショットを作成し、遷移アニメーション中はそのスナップショットを表示します。
この仕組みにより、進行中のリップルエフェクトなどのアニメーションが一時停止してしまいます。
allowSnapshottingの制御
allowSnapshotting
は以下の2つのパラメータで制御できます。
-
allowEnterRouteSnapshotting
: 新しいルートへの遷移時のスナップショット -
allowExitRouteSnapshotting
: 前のルートへの戻り時のスナップショット
設定変更の影響
設定 | メリット | デメリット |
---|---|---|
有効(デフォルト) | パフォーマンス向上、バッテリー節約 | アニメーション一時停止、UX違和感 |
無効 | 自然なアニメーション | 複雑なUIでパフォーマンス低下の可能性あり |
他の影響を受ける要素
この設定は以下の要素にも影響します。
-
CircularProgressIndicator
、LinearProgressIndicator
- カスタムアニメーション(
AnimationController
使用) - Lottieアニメーション
-
AnimatedContainer
、AnimatedOpacity
などのImplicit Animation
まとめ
リップルエフェクトの画面遷移時停止問題は、MaterialPageRoute
のallowSnapshotting
機能が原因でした。アプリ全体での統一性を考慮し、PageTransitionsTheme
での設定変更が適切と考えています。
この問題は、Android 10以降のZoomPageTransitionsBuilder
導入により顕在化しており、ユーザー体験を重視するアプリでは適切な対応が必要です。パフォーマンスと体験のバランスを考慮し、アプリの特性に応じて設定を選択することが重要です。
Discussion