Skip to content

Hero animation changes scroll offset of ListView after navigator.pop #31503

Closed

Description

@miguelcmedeiros

Steps to Reproduce

In the example app below we have 2 screens. The first one has a list view with multiple images and each image is has a Hero widget as an ancestor with a unique ID. If we scroll to the bottom of the list and tap on the image, we open the second screen that has the same widget (Hero with image). The issue happens when we pop the route and return to the first screen: the scroll offset is not the same as when we tapped on the card.

ezgif com-video-to-gif

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        home: FirstScreen(),
      );
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ListView(
          children: List<Widget>.generate(
            10,
            (index) => GestureDetector(
                  onTap: () => Navigator.of(context).push(MaterialPageRoute<void>(
                      builder: (BuildContext context) => SecondScreen(
                            Hero(
                              tag: index,
                              child: ImageWithLabel(index),
                            ),
                          ))),
                  child: Hero(
                    tag: index,
                    child: ImageWithLabel(index),
                  ),
                ),
          ),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  const SecondScreen(this.child);
  final Widget child;

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(),
        body: Center(child: child),
      );
}

class ImageWithLabel extends StatelessWidget {
  const ImageWithLabel(this.index);
  final int index;

  @override
  Widget build(BuildContext context) => Padding(
        padding: const EdgeInsets.symmetric(vertical: 4),
        child: Material(
          color: Colors.transparent,
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Image.network('https://picsum.photos/250?image=9'),
              Text(index.toString(), style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold)),
            ],
          ),
        ),
      );
}

Logs

[✓] Flutter (Channel unknown, v1.4.18, on Mac OS X 10.14.4 18E226, locale en-NL)
    • Flutter version 1.4.18 at /Users/user/IdeaProjects/project/flutter
    • Framework revision 8bea3fb2eb (12 days ago), 2019-04-11 13:11:22 -0700
    • Engine revision 72986c39ea
    • Dart version 2.2.1 (build 2.2.1-dev.3.1 None)

 
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at /Users/user/Library/Android/sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • 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)
    • All Android licenses accepted.

[!] iOS toolchain - develop for iOS devices (Xcode 10.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 10.2.1, Build version 10E1001
    ✗ Verify that all connected devices have been paired with this computer in Xcode.
      If all devices have been paired, libimobiledevice and ideviceinstaller may require updating.
      To update with Brew, run:
        brew update
        brew uninstall --ignore-dependencies libimobiledevice
        brew uninstall --ignore-dependencies usbmuxd
        brew install --HEAD usbmuxd
        brew unlink usbmuxd
        brew link usbmuxd
        brew install --HEAD libimobiledevice
        brew install ideviceinstaller
    • ios-deploy 2.0.0
    ✗ ios-deploy out of date (1.9.4 is required). To upgrade with Brew:
        brew upgrade ios-deploy
    • CocoaPods version 1.5.3

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

[✓] IntelliJ IDEA Community Edition (version 2019.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 34.0.4
    • Dart plugin version 191.6183.88

[✓] Connected device (2 available)
    • Miguel’s iPhone • 98b2b39514d586ebac7ee0537c84a7b23f8e46de • ios • iOS 12.2
    • iPhone Xʀ       • C140849E-3078-4185-B796-5FED4FCFE5EE     • ios • com.apple.CoreSimulator.SimRuntime.iOS-12-2 (simulator)

! Doctor found issues in 1 category.

Activity

  1. miguelcmedeiros commented on Apr 23, 2019

    @miguelcmedeiros
    Author

    @BaderEddineOuaich, in order for the Hero animation to happen when pushing a new route, it needs to find a Hero widget in the source route and another in the destination route with the exact same tag. Otherwise it won't fly 😉

  2. miguelcmedeiros commented on Apr 23, 2019

    @miguelcmedeiros
    Author

    @BaderEddineOuaich, every comment or hint are always welcome 👍
    With the code above, the hero animation happens, but it seems to misbehave when animating back to to the first screen for the last item of the list. Somehow the scroll offset of the list changes...

  3. added
    f: inspectorPart of widget inspector in framework.
    f: scrollingViewports, list views, slivers, etc.
    on Apr 30, 2019
  4. added this to the milestone on Apr 30, 2019
  5. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    on May 7, 2019
  6. self-assigned this
    on May 14, 2019
  7. Piinks commented on May 14, 2019

    @Piinks
  8. Piinks commented on May 14, 2019

    @Piinks
    Contributor

    I believe this behavior is due to size parameters not being specified for Image.network. According to the API docs:

    Either the width and height arguments should be specified, or the widget should be placed in a context that sets tight layout constraints. Otherwise, the image dimensions will change as the image is loaded, which will result in ugly layout changes.

    Adding just a height parameter in this example resolves the unexpected behavior (below), but can also be achieved by placing the image within another widget - such as a Container or ConstrainedBox - that provides the layout constraints mentioned in the docs.

    Image.network(
      'https://picsum.photos/250?image=9',
      height: 250,
    ),
    
    // or ...
    Container(
      height: 250,
      child: Image.network('https://picsum.photos/250?image=9'),
    ),
    
    // or ...
    
    ConstrainedBox(
      constraints: BoxConstraints.tight(const Size(250.0, 250.0)),
      child: Image.network('https://picsum.photos/250?image=9'),
    ),

    You can read more about Image.network here.
    Does this help with your issue @miguelcmedeiros?

  9. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on May 14, 2019
  10. miguelcmedeiros commented on May 16, 2019

    @miguelcmedeiros
    Author

    @Piinks, thanks to your input I was able to solve the issue. In my case I wrapper Image in a SizedBox with a given height.
    Thanks!!!

  11. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on May 16, 2019
  12. 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.

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

Assignees

Labels

customer: solarisf: inspectorPart of widget inspector in framework.f: scrollingViewports, list views, slivers, etc.frameworkflutter/packages/flutter repository. See also f: labels.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions