🔄

Flutter Android アプリでリップルエフェクトが画面遷移時に一時停止する問題

に公開

問題の発見

Flutter でAndroidアプリを開発している際、InkWellを利用したウィジェットからのPush遷移時に、タップしたウィジェットのリップルエフェクトが途中で一時停止する問題に遭遇しました。

この現象はInkWellだけでなく、ElevatedButtonFilledButtonなどのMaterialコンポーネント全般で発生していました。

具体的な動作は以下の通りです。

  1. Material系ウィジェットをタップ
  2. リップルアニメーションが開始
  3. Navigator.pushによる画面遷移が発生
  4. リップルアニメーションが途中で停止
  5. 遷移先から戻ると、停止していたアニメーションが再開


画面遷移後に戻ると、リップルエフェクトが再開される

開発環境情報

執筆時点での環境情報は以下の通りです。

$ 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

原因の調査

調査の結果、MaterialPageRouteallowSnapshottingプロパティが原因であることが判明しました。

allowSnapshotting(デフォルト:true)は、画面遷移時に現在のウィジェットツリーの静的なスナップショットを作成し、遷移アニメーション中にそのスナップショットを表示する機能です。これにより遷移中のパフォーマンスは向上しますが、進行中のアニメーション(リップルエフェクト、ProgressIndicatorなど)は一時停止されます。

解決方法

MaterialAppのテーマ設定でスナップショット機能を無効化

PageTransitionsThemeallowEnterRouteSnapshottingを無効化します。

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でパフォーマンス低下の可能性あり

他の影響を受ける要素

この設定は以下の要素にも影響します。

  • CircularProgressIndicatorLinearProgressIndicator
  • カスタムアニメーション(AnimationController使用)
  • Lottieアニメーション
  • AnimatedContainerAnimatedOpacityなどのImplicit Animation

まとめ

リップルエフェクトの画面遷移時停止問題は、MaterialPageRouteallowSnapshotting機能が原因でした。アプリ全体での統一性を考慮し、PageTransitionsThemeでの設定変更が適切と考えています。

この問題は、Android 10以降のZoomPageTransitionsBuilder導入により顕在化しており、ユーザー体験を重視するアプリでは適切な対応が必要です。パフォーマンスと体験のバランスを考慮し、アプリの特性に応じて設定を選択することが重要です。

参考資料

株式会社ガラパゴス(有志)

Discussion