Skip to content

Strange behavior for Hero applied to AppBar on iOS devices with notch. #27848

Closed

Description

@filipinascimento

Hi,

I'm observing a strange behavior for Hero animations applied to AppBar on iOS devices with notch (such as the iPhone X). Works fine for Android and other iOS devices. During the Hero animation, the content of the AppBar moves up and then down. I would expect it to be fixed since initial and last positions are the same. Also, I'm not sure if I'm doing anything wrong.

Here there is a minimal example to illustrate the problem:

void main() async {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  MyApp({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomeScreen(),
    );
  }
}

Widget _heroAppBar({BuildContext context,String titleText}){
    return PreferredSize(
      preferredSize: Size.fromHeight(kToolbarHeight),
      child: Hero(
          tag: 'app_bar',
          child: Builder(builder: (BuildContext context) {
            return AppBar(title:Text(titleText));
          }
        ),
      ),
    );
  }


class MyHomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar:_heroAppBar(context:context,titleText:"Home"),
      body:Center(
        child: IconButton(
          iconSize: 100,
          icon:Icon(Icons.play_arrow),
          onPressed: (){
            Navigator.push(context, MaterialPageRoute(builder: (context){
              return MyNextScreen();
            }));
          }
        ),
      )
    );
  }
}

class MyNextScreen extends StatelessWidget {
  Widget build(BuildContext context) {
    return  Scaffold(
        appBar:_heroAppBar(context:context,titleText:"Second"),
        body:Center(child:Text("Second Screen")),
        );
  }
}

I also attached a gif illustrating the problem.

On iPhone X

On iPhone 7

Flutter doctor:

[✓] Flutter (Channel beta, v1.1.8, on Mac OS X 10.14.3 18D109, locale en-US)
    • Flutter version 1.1.8 at /Users/filipi/Dropbox/flutter
    • Framework revision 985ccb6d14 (5 weeks ago), 2019-01-08 13:45:55 -0800
    • Engine revision 7112b72cc2
    • Dart version 2.1.1 (build 2.1.1-dev.0.1 ec86471ccc)

[!] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at /Users/filipi/Library/Android/sdk
    • Android NDK at /Users/filipi/Library/Android/sdk/ndk-bundle
    • Platform android-28, build-tools 28.0.3
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_152-release-1136-b06)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor
      --android-licenses

[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 10.1, Build version 10B61
    • ios-deploy 1.9.4
    • CocoaPods version 1.5.3

[✓] Android Studio (version 3.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 31.1.1
    • Dart plugin version 181.5656
    • Java version OpenJDK Runtime Environment (build
      1.8.0_152-release-1136-b06)

[✓] VS Code (version 1.31.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 2.22.3

[✓] Connected device (1 available)
    • iPhone 7 • E4F4A562-02D4-4217-8F18-91DF4D05CFB2 • ios • iOS 12.1
      (simulator)

! Doctor found issues in 1 category.

Activity

  1. added
    platform-iosiOS applications specifically
    frameworkflutter/packages/flutter repository. See also f: labels.
    f: routesNavigator, Router, and related APIs.
    on Feb 13, 2019
  2. added this to the milestone on Feb 13, 2019
  3. xster commented on Feb 26, 2019

    @xster
    Member

    In this case, I think the Hero's actual size (height specifically) actually encompasses areas under the notch. Though its parents specified a MediaQuery padding above the Hero so the AppBar below the Hero knows to draw the blue background under it but the title below it.

    When the AppBar is moved into an overlay, the overlay is likely not communicating the MediaQuery so the AppBar isn't pushing the title down.

    We likely need to find the MediaQuery padding of the default rect lerps and also lerp the MediaQuery value inside it.

  4. removed
    d: api docsIssues with https://api.flutter.dev/
    on Feb 26, 2019
  5. Hixie commented on Apr 12, 2019

    @Hixie
    Contributor

    I think it's actually the other way around, when it's in the Overlay, it's applying the bottom padding but in the Scaffold the Scaffold knows to remove it. I would just wrap the AppBar in a MediaQuery that has the bottom padding removed.

    Or use a CupertinoNavigationBar.

  6. xster commented on Apr 12, 2019

    @xster
    Member

    Ah, that could be it too. Either way, MediaQuery funkiness mid-flight should be the first thing to debug.

  7. Hixie commented on Apr 12, 2019

    @Hixie
    Contributor

    To be clearer about my last comment: I think this isn't a bug in Flutter. I think it's a bug in the app.

  8. LongCatIsLooong commented on Apr 19, 2019

    @LongCatIsLooong
    Contributor

    Hi @filipinascimento, thanks for reporting this issue!

    The MediaQuery around the app bar has a bottom padding on iOS devices with notch. The Scaffold usually takes care of the bottom padding for you, but when wrapped in a Hero, the app bar is taken out from the Scaffold during the animation so the bottom padding kicked in and pushed the content of the app bar up, as shown in your gif.

    Unfortunately we can't just ignore the bottom padding in the app bar because technically you can put the app bar at the bottom of your app, and removing the bottom padding from the app bar will break that.

    If you want to wrap the app bar in a Hero, you'll have to first wrap the app bar in a MediaQuery and remove the bottom padding (using your example):

    Hero(
      tag: 'app_bar',
      child: Builder(builder: (BuildContext context) {
        return MediaQuery.removePadding(
          context: context,
          child: AppBar(title:Text(titleText));,
          removeBottom: true,
          )
       }
    ),
    

    I'm going to close this issue. Feel free to reopen it if needed.

  9. feinstein commented on Feb 12, 2020

    @feinstein
    Contributor

    I think the AppBar docs should be further improved with an example on how to place the AppBar inside a MediaQuery, currently the docs just say:

    When not used as [Scaffold.appBar], or when wrapped in a [Hero], place the app
    bar in a [MediaQuery] to take care of the padding around the content of the
    app bar if needed, as the padding will not be handled by [Scaffold].

    What does place the app bar in a [MediaQuery] means?

    Is it:

    MediaQuery(
      data: MediaQuery.of(context),
      child: AppBar(
    ...
      ),
    )

    or

    MediaQuery.removePadding(
      context: context,
      child: AppBar(
    ...
      ),
    )

    ?

    From the docs I thought it was the first one, but looking at this issue found its the second.

  10. LongCatIsLooong commented on Feb 12, 2020

    @LongCatIsLooong
    Contributor

    @feinstein thanks for bringing this up! After re-reading the paragraph I too think I definitely didn't do a great job documenting that 😅 .
    I expanded this a bit hopefully this sounds more clear now:

    /// [AppBar] insets its content by [MediaQuery]'s padding, to avoid system UI intrusions. 
    /// It is imperative that the surrounding [MediaQuery] has the right padding values. When an [AppBar]
    /// is used outside of the [Scaffold.appBar] slot, or used in a [Hero] (which, when the hero animation plays, 
    /// will temporarily take the [AppBar] out of the [Scaffold.appBar] slot), it is recommended to wrap the 
    /// [AppBar] in a [MediaQuery] that has the current padding values like so:
    
    /// _Here goes a simple example_

    On a side note, closed issues are usually not as closely monitored. Feel free to open a new issue if you find similar problems on the master branch!

  11. feinstein commented on Feb 12, 2020

    @feinstein
    Contributor

    @LongCatIsLooong it's a lot clearer now thanks!

    And on the side note, I understand your point and I do open them a lot 😅, but usually when I comment on closed issues I tend to get an answer (and when I don't I open a new one), specially because people from the Flutter team are already assigned and up to speed on the problem.

  12. noobcoder17 commented on Mar 4, 2020

    @noobcoder17
    Hero(
      tag: 'hero',
      child: Builder(
        builder: (ctx){
          return  MediaQuery.removePadding(
            removeBottom: true,
            removeTop: true,
            removeLeft: true,
            removeRight: true,
            context: ctx,
            child: RaisedButton(
              color: Colors.red,
              onPressed: (){
                Navigator.of(context).pushNamed(SecondPage.routeName);
              },
            ),
          );
        },
      )
    ),
    

    I have done this for a hero transition of a raised button from one page to another. Is this wrong ? Because I am still having the padding issue.

  13. LongCatIsLooong commented on Mar 4, 2020

    @LongCatIsLooong
    Contributor

    @noobcoder17 that seems to be a different issue since I'm not seeing AppBar in your Hero. It's difficult to tell what the issue is from the code above. You can print out what the MediaQuery is in the Builder if you suspect something is wrong with MediaQuery.

    If you think it is an issue in the framework, could you open a new issue with a minimal reproducible example.

  14. github-actions commented on Aug 14, 2021

    @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.

  15. locked as resolved and limited conversation to collaborators on Aug 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

f: routesNavigator, Router, and related APIs.frameworkflutter/packages/flutter repository. See also f: labels.platform-iosiOS applications specifically

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions