Skip to content

Hero broken while overriding pageTransitions in ThemeData #163989

Closed

Description

@YukiAttano

Steps to reproduce

overriding

ThemeData(
  pageTransitionsTheme: const PageTransitionsTheme(
      builders: {
        TargetPlatform.android: SomeTransitionsBuilder(),
      },
    ),
)

will break Hero animations for all platforms that are not explicitly listed in builders.

Expected results

As this behavior has changed from 3.27.x to 3.29, it should be mentioned in the docs.

Until 3.29, the behavior was to override the transitions that were mentioned in the map and regarding the documentation it says

// page_transitions_theme.dart

/// If a builder with a matching platform is not found, then the
/// [ZoomPageTransitionsBuilder] is used.

(but i am sure that omitting a value would preserve the default behavior instead of using ZoomPageTransitionsBuilder)

Actual results

Hero Animations break if transition is not explicitly added.

Code sample

Example Repo:
https://github.com/YukiAttano/herotest

Screenshots or Video

Screenshots / Video demonstration

3.27.4 (expected behavior)

Herotest_3.27.4_cut.mp4

3.29.0 (actual behavior)

herotest_3.29.0_cut.mp4

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.29.0, on macOS 15.0.1 24A348 darwin-arm64, locale de-DE) [265ms]
    • Flutter version 3.29.0 on channel stable at /Users/yukiattano/Library/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 35c388afb5 (2 weeks ago), 2025-02-10 12:48:41 -0800
    • Engine revision f73bfc4522
    • Dart version 3.7.0
    • DevTools version 2.42.2

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [934ms]
    • Android SDK at /Users/yukiattano/Library/Android/sdk
    • Platform android-35, build-tools 35.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.4+-12422083-b607.1)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 16.2) [496ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16C5032a
    • CocoaPods version 1.16.2

[✓] Android Studio (version 2024.2) [8ms]
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.4+-12422083-b607.1)

[✓] Network resources [222ms]
    • All expected network resources are available.

• No issues found!

Activity

  1. brainwo commented on Feb 24, 2025

    @brainwo

    Worth noticing that the sample code for Hero widget are also all broken since 3.29.0.

    https://api.flutter.dev/flutter/widgets/Hero-class.html

  2. added
    in triagePresently being triaged by the triage team
    on Feb 25, 2025
  3. huycozy commented on Feb 25, 2025

    @huycozy
    Member

    Hi @YukiAttano
    To be clear, I see from your demo video (in 3.29.0), it's overriding a PageTransitionsBuilder for Android platform but hero animation is not applied when running on iOS, and vice versa, correct? And it's expected that the overrides transition animation is applied no matter target platform ( same as on 3.27.4), right?

  4. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Feb 25, 2025
  5. brainwo commented on Feb 25, 2025

    @brainwo
  6. huycozy commented on Feb 25, 2025

    @huycozy
  7. YukiAttano commented on Feb 25, 2025

    @YukiAttano
    Author

    Hi @YukiAttano
    To be clear, I see from your demo video (in 3.29.0), it's overriding a PageTransitionsBuilder for Android platform but hero animation is not applied when running on iOS, and vice versa, correct? And it's expected that the overrides transition animation is applied no matter target platform ( same as on 3.27.4), right?

    Mmmh, it meant to show that, overriding the builders parameter should only override the given platforms.

    As in 3.27, overriding Android and running on iOS does not break the transition on iOS while in 3.29, overriding Android breaks iOS.
    The reason is, that on the given "builders" parameter the defaults are no longer applied and so the default transition for iOS is missing which seem to be the reason the heros break.

    To be clear, the page transitions still work as expected while navigation. Only the heros break if no explicit value is given.

  8. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Feb 25, 2025
  9. huycozy commented on Feb 26, 2025

    @huycozy
    Member

    I have just set up Flutter 3.7.4. But I see the overridden transition animation is also only applied to the corresponding target platform. That being said, it's working as intended on 3.29.0, isn't it?
    I used the complete sample code below, can you also try and confirm?

    Sample code
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({
        super.key,
      });
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: const ExampleApp(),
          theme: ThemeData(
            pageTransitionsTheme: PageTransitionsTheme(
                builders: <TargetPlatform, PageTransitionsBuilder>{
                  TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
                }),
          ),
        );
      }
    }
    
    class ExampleApp extends StatelessWidget {
      const ExampleApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(child: TextButton(onPressed: (){
            Navigator.of(context).push(MaterialPageRoute(builder: (context) => const SecondPage()));
          }, child: Text('Go to next page'))),
        );
      }
    }
    
    class SecondPage extends StatelessWidget {
      const SecondPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(body: Text('Page 2'), appBar: AppBar(),);
      }
    }
    
  10. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Feb 26, 2025
  11. YukiAttano commented on Feb 26, 2025

    @YukiAttano
    Author

    I have just set up Flutter 3.7.4. But I see the overridden transition animation is also only applied to the corresponding target platform. That being said, it's working as intended on 3.29.0, isn't it?
    I used the complete sample code below, can you also try and confirm?

    Sample code
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({
        super.key,
      });
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: const ExampleApp(),
          theme: ThemeData(
            pageTransitionsTheme: PageTransitionsTheme(
                builders: <TargetPlatform, PageTransitionsBuilder>{
                  TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
                }),
          ),
        );
      }
    }
    
    class ExampleApp extends StatelessWidget {
      const ExampleApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(child: TextButton(onPressed: (){
            Navigator.of(context).push(MaterialPageRoute(builder: (context) => const SecondPage()));
          }, child: Text('Go to next page'))),
        );
      }
    }
    
    class SecondPage extends StatelessWidget {
      const SecondPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(body: Text('Page 2'), appBar: AppBar(),);
      }
    }
    

    That is not what i meant :)

    It is about the Hero Animation.
    The Hero breaks if the page transition is changed according to my description.

    Which should not happen.

  12. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Feb 26, 2025
  13. huycozy commented on Feb 27, 2025

    @huycozy
    Member

    It is about the Hero Animation.
    The Hero breaks if the page transition is changed according to my description.

    Can you please elaborate on how the Hero animation breaks ? Doesn't it work? Or something else?

  14. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Feb 27, 2025
  15. YukiAttano commented on Feb 27, 2025

    @YukiAttano
    Author

    It is about the Hero Animation.
    The Hero breaks if the page transition is changed according to my description.

    Can you please elaborate on how the Hero animation breaks ? Doesn't it work? Or something else?

    Yeah well ehm. Thats why i've added the repo and the videos.

    Basically, you are testing on iOS and have the Hero animation set up.
    Everything works in 3.27.

    Now you do override the Theme.pageTransition for Android.

    Your iOS app runs fine.

    After updating Flutter to 3.29, you do nothing else, the Hero Animation breaks on iOS.

    The reason seems to be the Theme.pageTransition.
    If you don't explicitly define any transition, everything works fine.
    If you copy the defaults and only override Android, everything works fine.

    But if you want to change the transition for Android, Web or any other only, all other platforms will break the Hero Animation.
    And this is not how Flutter up to 3.27 worked.

    Hope that clarifies something, i can only repeat myself from now on.
    I recommend to repeat the steps in my video.

    Test the Hero Animation on iOS with and without overriding the pageTransition for any other Platform (or test on Android and override iOS for example).

    You will see that the Hero Animation breaks.
    If you downgrade to 3.27, you'll see that i didn't break.

  16. 6 remaining items

  17. added
    f: routesNavigator, Router, and related APIs.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    team-designOwned by Design Languages team
    frameworkflutter/packages/flutter repository. See also f: labels.
    on Feb 28, 2025
  18. added
    P2Important issues not at the top of the work list
    triaged-designTriaged by Design Languages team
    on Mar 12, 2025
  19. esDotDev commented on Mar 29, 2025

    @esDotDev

    Very frustrating, this probably cost us an entire day trying to figure out why Heros were mysteriously broken on Windows and Linux when using anything other than a CupertinoApp.

    Looks like the new defaults, buried at line 1085 in page_transition_theme are

    static const Map<TargetPlatform, PageTransitionsBuilder> _defaultBuilders =
          <TargetPlatform, PageTransitionsBuilder>{
            TargetPlatform.android: ZoomPageTransitionsBuilder(),
            TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
            TargetPlatform.macOS: CupertinoPageTransitionsBuilder(),
          };

    So it looks like we now must pass in a full list of builders to our app in order to get functioning Heros on Windows/Linux?

    MaterialApp(
      theme: ThemeData(
            pageTransitionsTheme: PageTransitionsTheme(builders: {
              TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
              TargetPlatform.macOS: CupertinoPageTransitionsBuilder(),
              TargetPlatform.windows: ZoomPageTransitionsBuilder(),
              TargetPlatform.android: ZoomPageTransitionsBuilder(),
              TargetPlatform.linux: ZoomPageTransitionsBuilder(),
            }),
          ),
  20. added a commit that references this issue on Apr 2, 2025
    9a6ae31
  21. github-actions commented on Apr 16, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  22. locked as resolved and limited conversation to collaborators on Apr 16, 2025
  23. added a commit that references this issue on Jun 9, 2025
    9d659e5
  24. added a commit that references this issue on Aug 14, 2025
    944de94
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: animationAnimation APIsc: regressionIt was better in the past than it is nowf: routesNavigator, Router, and related APIs.found in release: 3.29Found to occur in 3.29found in release: 3.30Found to occur in 3.30frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: material_uimaterial_ui package in flutter/packagesteam-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions