tp7309 / flutter_sticky_and_expandable_list

粘性头部与分组列表Sliver实现 Build a grouped list, which support expand/collapse section and sticky headers, support use it with sliver widget.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ExpandableListHeaderController.percent jumps from 0.9 to 0.0 during scroll

emvaized opened this issue · comments

Screenshot_20200317_050741

Please implement more intuitive behavior, for all 3 states of header: like -1.0 for header being off-screen, 0.0 for pinned, and 1.0 for not-pinned (floating) header, as it is implemented here.

I don't want callback header offset every frame.You can get such information:

  • pinned header index ExpandableListHeaderController.stickySectionIndex
  • floating header index ExpandableListHeaderController.switchingSectionIndex

Maybe example_animable_header can give you some tips. ^_^

@tp7309
Thanks :)
I'm currently using this approach to create a shadow below header only when it's pinned on top:

Card(
        elevation:
            stickyController.stickySectionIndex == sectionIndex
                ? 3
                : 0,
)

But it works with some issues -- for example, when there's padding on top of the list, header of the first card always has shadow, even when it's not pinned.
Maybe I'm just missing something?

Padding on top of the list?
Could you give me an example?

For example (approximation of my use case):

CustomScrollView(
  slivers: [
    /// First child of my CustomScrollView, which can be considered as a 'padding'
    SliverToBoxAdapter(
       child: Container(height: 100, width: 100)
    ),
    ExpandableListView(
        controller: stickyController,
        builder: SliverExpandableChildDelegate<String, ExampleSection>(
            headerBuilder: (context, section, index) => Text("Header #$index"),
            itemBuilder: (context, section, item, index) {
            int sectionIndex = sectionList.indexOf(section); 
               return Card(
                  elevation:
                      stickyController.stickySectionIndex == sectionIndex
                        ? 3
                        : 0, /// <-- when list is scrolled to top, first header never reach this value
                  child: Text(item),
              );
         }
    ))
  ]
);

@tp7309
Previously I used flutter_sticky_headers, and with implementation below there were no problems:

...
return Card(
    elevation: stickiness < 0.0 ? 3 : 0,
    child: Text(item)
)

That's why I suggested to implement some analog of stickiness parameter, with values of -1.0 (completely off-screen), 0.0 ('sticked') and 1.0 (not sticked, floating).

@emvaized
Thanks for your feedback! Built-in animation are planned to be added in this weekend!
For your feature, you can try the following code:

class _ExampleSliverState extends State<ExampleSliver> {
  var sectionList = MockData.getExampleSections();

  int _stickySectionIndex = -1;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: CustomScrollView(slivers: [
          /// First child of my CustomScrollView, which can be considered as a 'padding'
          SliverToBoxAdapter(child: Container(height: 100, width: 100)),
          SliverExpandableList(
              builder: SliverExpandableChildDelegate<String, ExampleSection>(
                  sectionList: sectionList,
                  headerController: _getHeaderController(),
                  headerBuilder: (context, section, index) {
                    int sectionIndex = sectionList.indexOf(section);
                    return Card(
                      elevation: _stickySectionIndex == sectionIndex ? 10 : 0,
                      child: Text("Header #$index"),
                    );
                  },
                  itemBuilder: (context, section, item, index) {
                    int sectionIndex = sectionList.indexOf(section);
                    return Card(
                      elevation: _stickySectionIndex == sectionIndex ? 10 : 0,
                      child: Text(item),
                    );
                  }))
        ]),
      ),
    );
  }

  _getHeaderController() {
    var controller = ExpandableListHeaderController();
    //when changing sticky header, listener will be called.
    controller.addListener(() {
      /// if you want call itemBuilder when changing sticky header, call setState() manually.
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (!mounted || _stickySectionIndex == controller.stickySectionIndex) {
          return;
        }
//        print(controller);
        setState(() {
          _stickySectionIndex = controller.stickySectionIndex;
        });
      });

      /// if you only want call headerBuilder when changing sticky header, no need to call setState().
      /// just change some value in headerBuilder.
    });
    return controller;
  }
}

@tp7309
Previously I used flutter_sticky_headers, and with implementation below there were no problems:

...
return Card(
    elevation: stickiness < 0.0 ? 3 : 0,
    child: Text(item)
)

That's why I suggested to implement some analog of stickiness parameter, with values of -1.0 (completely off-screen), 0.0 ('sticked') and 1.0 (not sticked, floating).

It will trigger widget rebuild high frequency, so if you need rebuild item widget, call setState() manually is another option.

@tp7309
Very nice! Will be glad to try out these animations.

About subject:
Please let me illustrate my issue with this GIF (with your solution already implemented):
ezgif com-video-to-gif(2)

The issue I mentioned above can be seen in the end of this GIF, and your solution created another issue, that can be seen in the beginning of GIF (previous header keeps at elevation == 0 despite being over content).

There has a bug, when scroll out SliverExpandableList, stickySectionIndex are not updated, I'm trying to fix it.

@tp7309
Oh, I see now.
Glad you're working on it! I'll be waiting for updates.

@emvaized Hi, I have updated the library, you can try to use 0.2.0-beta.
In order to use it more conveniently, some API changed, so you may need read the lastest REMDME.
fixed animable header example

@tp7309 I see. A lot of changes :)
Seems like bug is fixed now. Great, thanks a lot for your work!

@emvaized
Thank you for you feedback:)