Kavantix / sliver_tools

A set of useful sliver tools that are missing from the flutter framework
MIT License
652 stars 64 forks source link

Wrong calculations for multiple pinned SliverPersistentHeader inside a NestedScrollView #62

Open papmodern opened 2 years ago

papmodern commented 2 years ago

I had a section in my app which contains a appbar a top section and tab bar which all of them are implemented with NestedScrollView and MultiSliver. It was working fine but it came up problematic after I removed my pubspec.lock file.

Recent problem: image

Previously correct behavior image

Therefore I realized this feature of the lib is corrupted from version 0.2.5 to 0.2.8

I'm working on Flutter 2.10.5

I used the lib with 0.2.5 exact version as dependency_overrides and its working correctly now. But I wanted to inform you about this new bug

I can describe the wrong behavior in this way. Whenever you add more than one SliverPersistentHeader or SliverAppBar with pinned: true property, the first one works fine, but the rest of the slivers can't understand the position and they don't receive shrinkOffset changes. Also the body of the NestedScrollView goes behind these widgets(The ones after the first pinned widget).

Kavantix commented 2 years ago

Hi @papmodern thanks for opening an issue! It would be helpful if you could provide a minimal example that reproduces the problem.

In 0.2.8 I fixed #56 which was also related to NestedScrollView, could you test with 0.2.7 to see if that’s what caused this?

papmodern commented 2 years ago

It is working fine with 0.2.7 too. The bugs is specified only to 0.2.8 version

This is a sample code to demonstrate the problem:


class SampleWidget extends StatelessWidget {
  const SampleWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverOverlapAbsorber(
                handle:
                    NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                sliver: MultiSliver(
                  children: [
                    SliverAppBar(
                      pinned: true,
                      title: Text('First AppBar'),
                      expandedHeight: 100,
                      collapsedHeight: 60,
                    ),
                    SliverAppBar(
                      pinned: true,
                      title: Text('Second AppBar'),
                      expandedHeight: 200,
                      collapsedHeight: 60,
                      backgroundColor: Colors.red,
                    ),
                    SliverAppBar(
                      pinned: true,
                      title: Text('Third AppBar'),
                      expandedHeight: 200,
                      collapsedHeight: 60,
                      backgroundColor: Colors.yellow,
                    ),
                  ],
                ),
              ),
            ];
          },
          body: ListView.builder(
            itemBuilder: (c, i) => ListTile(
              title: Text('Item $i'),
            ),
          ),
        ),
      ),
    );
  }
}`
Kavantix commented 2 years ago

@papmodern are you sure that the problem that existed in #56 is not occurring for you before 0.2.8 (because in my testing it does). The underscroll bug is actually a bug in flutter itself: flutter/flutter#110937

Either way I would recommend not to use a NestedScrollView, you can implement the example above without it. Note that the behaviour there is also not what you would like to have.

class SampleWidget extends StatelessWidget {
  const SampleWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: CustomScrollView(
          slivers: [
            SliverAppBar(
              pinned: true,
              title: Text('First AppBar'),
              expandedHeight: 100,
              collapsedHeight: 60,
            ),
            SliverAppBar(
              pinned: true,
              title: Text('Second AppBar'),
              expandedHeight: 200,
              collapsedHeight: 60,
              backgroundColor: Colors.red,
            ),
            SliverAppBar(
              pinned: true,
              title: Text('Third AppBar'),
              expandedHeight: 200,
              collapsedHeight: 60,
              backgroundColor: Colors.yellow,
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (c, i) => ListTile(
                  title: Text('Item $i'),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Kavantix commented 2 years ago

Also, SliverAppBar doesnt actually have any code to support multiple pinned ones that can collapse so I would suggest opening an issue in the flutter repo for that

papmodern commented 2 years ago

@Kavantix In the real app I faced the problem, I have tab bar and tab bar view and each tab has its own scrollview. So I have to use NestedScrollView. The code I wrote for you is only for demonstrating the problem. Even SliverOverlapAbsorber is not necessary here and if you remove just this one, everything works fine. I tried several times and for me it only happens with 0.2.8. I check the version code from pubspec.lock to make sure which version is resolving.