pulyaevskiy / parallax-image

A Flutter widget that paints an image and moves it at a slower speed than the main scrolling content.
BSD 3-Clause "New" or "Revised" License
279 stars 33 forks source link

"The getter 'position' was called on null" #4

Closed henryla92 closed 5 years ago

henryla92 commented 5 years ago

Hi, I get the error "The getter 'position' was called on null" during the transition when I combine ParallaxImage with Hero transition. The error message goes away after the animation.

Like below:

Hero( tag: 'hero', child: ClipRRect( borderRadius: BorderRadius.vertical(top: Radius.circular(5.0)), child: ParallaxImage( image: AssetImage('lib/images/tile.jpg'), extent: 300, ), ), )

Please help.

Thanks!

pulyaevskiy commented 5 years ago

Hi,

Could you provide a more complete example which includes the origin and destination layouts for the Hero? (You can put in a https://gist.github.com/ which is a bit more friendly to big chunks of code.)

I suspect that ParallaxImage gets detached from its Scrollable during transition which results in an error.

henryla92 commented 5 years ago

Hi,

Here are the two files, the home page has a "tile" that can be clicked on and that image should become the header of the article page:

https://gist.github.com/henryla92/024d2f3a6f416ce2fc371d1309a0f0ad

Thanks!

pulyaevskiy commented 5 years ago

Hey @henryla92 ,

Sorry for the delay here. Thanks for the example, it helped and I'm able to reproduce this error.

Not sure yet what would be a proper fix for this though. The reason it shows an errors is that Hero widget created on the ArticleScreen seems to be created detached from its ListView.

There is a very simple workaround for this if you are interested: you simply need to provide an instance of ScrollController to ParallaxImage and the ListView. E.g.

class ArticlePage extends StatefulWidget {
  @override
  ArticlePageState createState() => ArticlePageState();
}

class ArticlePageState extends State<ArticlePage> {
  final ScrollController _controller = ScrollController();

  @override
  Widget build(BuildContext context) {
    /// When creating [ParallaxImage] set `controller` argument:
    final header = ParallaxImage(controller: _controller, /* .. */);
    /// Similarly with ListView
    return ListView(controller: _controller, children: [header]);
  }

This would make the error to go away.

henryla92 commented 5 years ago

Hi,

Thanks! It worked!

henryla92 commented 5 years ago

Not sure yet what would be a proper fix for this though. The reason it shows an errors is that Hero widget created on the ArticleScreen seems to be created detached from its ListView.

Would this be because of me embedding a PageView within a ListView? That is what I have on my homepage.

Also, on the way back from the ArticlePage to HomePage the same error shows up, I tried to add a controller but after that, the parallax image stops showing up.

pulyaevskiy commented 5 years ago

Would this be because of me embedding a PageView within a ListView?

It looks like mostly due to the use of Hero widgets here. When it animates from one screen to another it does not have any Scrollable ancestor which is required for parallax effect to work.

I tried to add a controller but after that, the parallax image stops showing up.

Did you also pass that controller to your PageView?

henryla92 commented 5 years ago

It looks like mostly due to the use of Hero widgets here. When it animates from one screen to another it does not have any Scrollable ancestor which is required for parallax effect to work.

Ah that makes sense

controller:PageController(viewportFraction: 0.80, initialPage: 0),

I have this as my controller for my page view, I tried to pass the same controller to page view as well but it only takes PageController.

pulyaevskiy commented 5 years ago

You'll have to do it the other way around: pass PageController to parallax image.

PageController extends ScrollController so it should work.

Note that you might want to extract creation of this controller outside of build() method of your page so that it is not re-created on every build.

henryla92 commented 5 years ago

I tried using PageController on both the pages and only on homepage, the error goes away but the image with the controller still won't show up.

pulyaevskiy commented 5 years ago

Here is how I modified your example, which works for me: https://gist.github.com/pulyaevskiy/74250db49297f754f68350e1798afaa2

  1. I converted both pages to StatefulWidgets
  2. In HomePageState I initialize PageController and pass it all the PageView and all ParallaxImages
  3. In ArticlePageState I initialize ScrollController and pass it to the ListView and ParallaxImage.

(note that I had to change actual image resources but it's not relevant).

Hope this helps.

henryla92 commented 5 years ago

Great! It works perfectly now.

Thank you so much!

robisaks commented 5 years ago

I was also getting this error when going back to the main screen from a subscreen using a hero image. Passing the scroll controller worked great, thanks!