Build a grouped list, which support expand/collapse section and sticky headers, support use it with sliver widget.

Overview

sticky_and_expandable_list

Flutter implementation of sticky headers and expandable list.Support use it in a CustomScrollView.

Pub README i18n:中文说明

Screenshot

Features

  • Build a grouped list, which support expand/collapse section and sticky header.
  • Use it with CustomScrollView、SliverAppBar.
  • Listen the scroll offset of current sticky header, current sticky header index and switching header index.
  • Only use one list widget, so it supports large data and a normal memory usage.
  • More section customization support, you can return a new section widget by sectionBuilder, to customize background,expand/collapse animation, section layout, and so on.
  • Support add divider.
  • Support overlap content.
  • Support scroll to index like ListView, by scroll-to-index.

Getting Started

In the pubspec.yaml of your flutter project, add the following dependency:

dependencies:
  sticky_and_expandable_list: ^1.0.3

Basic Usage

sectionList is a custom data source for ExpandableListView. We should create a model list to store the information of each section, the model must implement ExpandableListSection.

    //In this example, we create a custom model class(ExampleSection).
    //class ExampleSection implements ExpandableListSection
   
     {}
   
    //so: SliverExpandableChildDelegate
   
    ()
   
    List<ExampleSection> sectionList = List<ExampleSection>();
    return ExpandableListView(
      builder: SliverExpandableChildDelegate<String, ExampleSection>(
          sectionList: sectionList,
          headerBuilder: (context, sectionIndex, index) =>
              Text("Header #$sectionIndex"),
          itemBuilder: (context, sectionIndex, itemIndex, index) {
            String item = sectionList[sectionIndex].items[itemIndex];
            return ListTile(
              leading: CircleAvatar(
                child: Text("$index"),
              ),
              title: Text(item),
            );
          }),
    );

Detail Examples

If you want to use it with sliver widget, use SliverExpandableList instead of ExpandableListView.

FAQ

How to expand/collapse item?

setState(() {
  sectionList[i].setSectionExpanded(true);
});

Example

How to listen current sticky header or the sticky header scroll offset?

  @override
  Widget build(BuildContext context) {
    ExpandableListView(
      builder: SliverExpandableChildDelegate<String, ExampleSection>(
        headerController: _getHeaderController(),
      ),
    )
  }

  _getHeaderController() {
    var controller = ExpandableListController();
    controller.addListener(() {
      print("switchingSectionIndex:${controller.switchingSectionIndex}, stickySectionIndex:" +
          "${controller.stickySectionIndex},scrollPercent:${controller.percent}");
    });
    return controller;
  }

How to set background for each section?

Use sectionBuilder

Customize expand/collapse animation support?

Example

Change Log

CHANGELOG

Donate

Buy a cup of coffee for me (Scan by wechat):

qrcode

Comments
  • ExpandableListHeaderController.percent jumps from 0.9 to 0.0 during scroll

    ExpandableListHeaderController.percent jumps from 0.9 to 0.0 during scroll

    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.

    bug 
    opened by emvaized 13
  • Error regarding dispose when scroll halfway through the section and collapse the section

    Error regarding dispose when scroll halfway through the section and collapse the section

    I was testing on the custom section animation example and was trying to replace list tile text with an image as shown below, the error happens when i scroll halfway through the section and tap the header to collapse the section. Simulator Screen Shot - iPhone SE (2nd generation) - 2020-09-18 at 14 32 55 Screenshot 2020-09-18 at 1 46 25 PM

    opened by lemy319 11
  • 展开一个Header#0 滑动一点点, 然后展开第二个的时候,Header#1时候,展开不是现实的第一个ListTitle#0这条数据

    展开一个Header#0 滑动一点点, 然后展开第二个的时候,Header#1时候,展开不是现实的第一个ListTitle#0这条数据

    xin

    Hello, I have a situation here. I'm going to expand one Header#0 by sliding a little bit, and then I'm going to expand the second one, and then I'm going to expand the first ListTitle#0 that's not actually real, and occasionally I'm going to flash. Don't know how to solve this?

    demo Repetition can be

    您好,我这边出现这种情况。展开一个Header#0 滑动一点点, 然后展开第二个的时候,Header#1时候,展开不是现实的第一个ListTitle#0这条数据,偶尔还有闪屏的情况。不知道这个怎么解决?

    demo可复现

    opened by yj229201093 10
  • Animation issue, header jumps to top after animation

    Animation issue, header jumps to top after animation

    Hi, thank you for your work on this package.

    I noticed an animation issue on larger lists.

    1. set /MockData/.getExampleSections(3, 12);
    2. Open CustomSectionAnimation Example
    3. scroll to bottom
    4. collapse header #2
    5. Note that during the animation header #1 sticks to header #2 until section #2 collapse is finished, after that header #1 jumps to top.

    2020-10-06 13 59 32

    opened by mkoorn 9
  • Usage with Dismissible widget

    Usage with Dismissible widget

    How to properly remove section from screen in onDismissed() callback of Dismissible widget? I tried to call widget.fetchedData.removeAt(position), but it seems to fail, resulting in 'RangeError (index)'.

    help wanted 
    opened by emvaized 7
  • Error NoSuchMethodError in the example

    Error NoSuchMethodError in the example

    When building any example, an error is written in the debag (I attach the log below). What is the reason for it and how to fix it? When scrolling the list, it is repeated.

    Flutter 1.17.0 Dart 2.8.1

    debug log

    Launching lib/main.dart on iPhone 11 Pro Max in debug mode... Xcode build done. 9,4s

    ════════ Exception caught by rendering library ═════════════════════════════════ The following NoSuchMethodError was thrown during performLayout(): The method '>' was called on null. Receiver: null Tried calling: >(0)

    The relevant error-causing widget was ExpandableSectionContainer When the exception was thrown, this was the stack #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5) #1 RenderExpandableSectionContainer.performLayout #2 RenderObject.layout #3 RenderProxyBoxMixin.performLayout #4 RenderObject.layout ... The following RenderObject was being processed when the exception was fired: RenderExpandableSectionContainer#0ab60 relayoutBoundary=up5 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE RenderObject: RenderExpandableSectionContainer#0ab60 relayoutBoundary=up5 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE needs compositing parentData: (can use size) constraints: BoxConstraints(w=414.0, 0.0<=h<=Infinity) size: Size(414.0, 224.0) child 1: RenderClipRect#cabbc relayoutBoundary=up6 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: offset=Offset(0.0, 56.0); id=null (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 168.0) child: RenderPositionedBox#807d2 relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 168.0) alignment: AlignmentDirectional.centerStart textDirection: ltr widthFactor: expand heightFactor: 1.0 child: RenderFlex#b3e29 relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: offset=Offset(0.0, 0.0) (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 168.0) direction: vertical mainAxisAlignment: start mainAxisSize: max crossAxisAlignment: center verticalDirection: down child 1: RenderSemanticsAnnotations#16f4f relayoutBoundary=up9 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: offset=Offset(0.0, 0.0); flex=null; fit=null (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 56.0) child 2: RenderSemanticsAnnotations#441e3 relayoutBoundary=up9 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: offset=Offset(0.0, 56.0); flex=null; fit=null (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 56.0) child 3: RenderSemanticsAnnotations#2956d relayoutBoundary=up9 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: offset=Offset(0.0, 112.0); flex=null; fit=null (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 56.0) child 2: _RenderColoredBox#2653f relayoutBoundary=up6 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: offset=Offset(0.0, 0.0); id=null (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 56.0) behavior: opaque child: RenderSemanticsAnnotations#51d35 relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 56.0) child: RenderMouseRegion#d1710 relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 56.0) listeners: enter, exit child: RenderSemanticsGestureHandler#ba4af relayoutBoundary=up9 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE parentData: (can use size) constraints: BoxConstraints(0.0<=w<=414.0, 0.0<=h<=Infinity) size: Size(414.0, 56.0) gestures: tap ════════════════════════════════════════════════════════════════════════════════

    ════════ Exception caught by rendering library ═════════════════════════════════ The method '>' was called on null. Receiver: null Tried calling: >(0) The relevant error-causing widget was ExpandableSectionContainer ════════════════════════════════════════════════════════════════════════════════

    bug 
    opened by karavanov 6
  • Sticky header issue in Tab layout

    Sticky header issue in Tab layout

    I am trying to implement the ExampleCustomSectionAnimation in a TabLayout

    image

    But as soon as I scroll and the AppBar collapses the header no longer remains sticky and gets under the AppBar. This AppBar is in the TabLayout Main view

    image

    But if give another AppBar in the ExampleCustomSectionAnimation list view - In Red over here

    image

    The header becomes sticky again

    image

    I want the headers to remain sticky without the additional AppBar (Red),

    Thanks for the package, Love it!

    The issue can be easily replicated by placing the ExampleCustomSectionAnimation provided in the sample in a TabBarView

    MainTabLayout image

    opened by Shamik07 5
  • NestedScrollView SliverAppBar and sticky header overlap

    NestedScrollView SliverAppBar and sticky header overlap

    This package has been really great for creating complex applications but I've had trouble now implementing the SliverExpandableList with a NestedScrollView. Specifically, the sticky header overlaps with the SliverAppBar I have in the headerSliver section of the NestedScrollView when the pin option is set to true. If I set pin to false there will no longer be any overlap but for the purposes of my application I need the appbar to be pinned.

    I saw in another issue someone mentioned something similar and they used a SafeArea widget around the CustomScrollView to circumvent this, however this only fixes this issue when pin is set to false. Similarly, using a regular appbar within the scaffold with the toolbarheight set to 0 has the same effect as using the SafeArea widget. I tested with the example application listed to find a solution to no avail. This is what it looks with a SafeArea widget around the CustomScrollView vs without:

    As you can see while the SafeArea widget does fix the header from being trapped in the statusbar, it is now stuck within the sliverappbar. After reading the NestedScrollView documentation here are the series of steps I've tried:

    1. According to the NestedScrollView documentation, SliverOverlapAbsorber and SliverOverlapInjector should stop the body from scrolling underneath the sliverappbar, however this does not seem to be the case. It still refuses to respect the sliverappbar.

    2. Setting floating to true instead of pinned does not work as intended either. The sliverappbar never appears when scrolling upwards even if I set "floatHeaderSlivers" of NestedScrollView to true.

    3. Setting floating and snapped to true also does not resolve this issue. While it does show the sliverappbar when I scroll up now, it completely overlaps the body. Additionally, setting "floatHeaderSlivers" of NestedScrollView to true with these options does not change this behavior. image

    Any ideas on how to solve this issue? It would be greatly appreciated. The code below is based off the code from the example in this package.

    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      var sectionList = MockData.getExampleSections();
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          home: Scaffold(
            // appBar: AppBar(
            //   toolbarHeight: 0,
            // ),
            body: NestedScrollView(
              // floatHeaderSlivers: true,
              headerSliverBuilder: (context, innerBoxIsScrolled) => [
                // SliverOverlapAbsorber(
                //   handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                //   sliver:
                SliverAppBar(
                  backgroundColor: Colors.transparent,
                  // pinned: true,
                  floating: true,
                  snap: true,
                  expandedHeight: 200,
                  flexibleSpace: FlexibleSpaceBar(
                    title: Text("Sliver Example"),
                  ),
                ),
                // ),
              ],
              body: SafeArea(
                child: Builder(
                  builder: (context) => CustomScrollView(
                    slivers: <Widget>[
                      // SliverOverlapInjector(
                      //   handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
                      //       context),
                      // ),
                      SliverExpandableList(
                        builder:
                            SliverExpandableChildDelegate<String, ExampleSection>(
                          sectionList: sectionList,
                          headerBuilder: _buildHeader,
                          itemBuilder: (context, sectionIndex, itemIndex, index) {
                            String item =
                                sectionList[sectionIndex].items[itemIndex];
                            return ListTile(
                              leading: CircleAvatar(
                                child: Text("$index"),
                              ),
                              title: Text(item),
                            );
                          },
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
        );
      }
    
    [√] Flutter (Channel stable, 1.22.2, on Microsoft Windows [Version 10.0.19041.610], locale en-US)
        • Flutter version 1.22.2 at C:\flutter
        • Framework revision 84f3d28555 (3 weeks ago), 2020-10-15 16:26:19 -0700
        • Engine revision b8752bbfff
        • Dart version 2.10.2
    
     
    [√] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
        • Android SDK at C:\Users\aaqib\AppData\Local\Android\sdk
        • Platform android-30, build-tools 30.0.2
        • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
        • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
        • All Android licenses accepted.
    
    [!] Android Studio (version 4.1.0)
        • Android Studio at C:\Program Files\Android\Android Studio
        X Flutter plugin not installed; this adds Flutter specific functionality.
        X Dart plugin not installed; this adds Dart specific functionality.
        • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    
    [√] VS Code (version 1.50.1)
        • VS Code at C:\Users\aaqib\AppData\Local\Programs\Microsoft VS Code
        • Flutter extension version 3.16.0
    
    [√] Connected device (1 available)
        • sdk gphone x86 (mobile) • emulator-5554 • android-x86 • Android 11 (API 30) (emulator)
    
    ! Doctor found issues in 1 category.
    
    opened by aaqibismail 5
  • Migrate to 3.0.0

    Migrate to 3.0.0

    ../../flutter/.pub-cache/hosted/pub.flutter-io.cn/sticky_and_expandable_list-1.0.3/lib/src/expandable_section_container.dart:170:22: Warning: Operand of null-aware operation '?.' has type 'WidgetsBinding' which excludes null.

    • 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../flutter/packages/flutter/lib/src/widgets/binding.dart'). WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { ^ ../../flutter/.pub-cache/hosted/pub.flutter-io.cn/sticky_and_expandable_list-1.0.3/lib/src/sliver_expandable_list.dart:410:22: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    • 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../flutter/packages/flutter/lib/src/widgets/binding.dart'). WidgetsBinding.instance!.addPostFrameCallback((_) { ^
    opened by M2dL1fe 4
  • The SliverExpandableList isn't reversible

    The SliverExpandableList isn't reversible

    It looks as if the SliverExpandableList isn't reversible (the ExpandableListView is). Is there a way to get this sort of behaviour (reversing and starting at the bottom)? Thanks!

    opened by Ben-Baert 4
  • 当items 为空或者items.length =0 时有问题,

    当items 为空或者items.length =0 时有问题,

    The method '_addFromInteger' was called on null. Receiver: null Tried calling: _addFromInteger(1)

    The relevant error-causing widget was: ExampleListView file:///Users/mac/Downloads/flutter_sticky_and_expandable_list-master/example/lib/main.dart:43:50 When the exception was thrown, this was the stack: #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5) #1 int.+ (dart:core-patch/integers.dart:12:38) #2 SliverExpandableChildDelegate._buildSectionRealIndexes (package:sticky_and_expandable_list/src/sliver_expandable_list.dart:214:22) #3 new SliverExpandableChildDelegate (package:sticky_and_expandable_list/src/sliver_expandable_list.dart:81:30) #4 _ExampleListViewState.build (package:example/example_listview.dart:18:20)

    bug 
    opened by liaoli 4
Releases(v1.1.2)
Owner
tp7309
tp7309
Flutter Sticky Headers - Lets you place

Flutter Sticky Headers Lets you place headers on scrollable content that will stick to the top of the container whilst the content is scrolled. Usage

Flutter Community 901 Dec 28, 2022
A Flutter sticky headers & index ListView. Based on scrollable_positioned_list.

Language: English | 中文简体 azlistview A Flutter sticky headers & index ListView. Based on scrollable_positioned_list. AzListView, SuspensionView, IndexB

Flutter中国开源项目 971 Jan 7, 2023
A flutter grouped list widget similar to the iOS UITableview method name.

group_tablelist A flutter grouped list widget similar to the iOS UITableview method name. Group tablelist package for Flutter. Features iOS tableview-

null 2 Aug 17, 2022
Flutter Color Picker Wheel - an easy to use widget which can be heavily customized

Flutter Color Picker Wheel Flutter Color Picker Wheel is an easy to use widget which can be heavily customized. You can use the WheelColorPicker direc

Kexin Lu 35 Oct 4, 2022
A flutter carousel widget, support infinite scroll, and custom child widget.

carousel_slider A carousel slider widget. Features Infinite scroll Custom child widgets Auto play Supported platforms Flutter Android Flutter iOS Flut

Bart T 1 Nov 25, 2021
📸 Easy to use yet very customizable zoomable image widget for Flutter, Photo View provides a gesture sensitive zoomable widget.

?? Easy to use yet very customizable zoomable image widget for Flutter, Photo View provides a gesture sensitive zoomable widget. Photo View is largely used to show interacive images and other stuff such as SVG.

Blue Fire 1.7k Jan 7, 2023
Provider support for overlay, make it easy to build toast and In-App notification.

overlay_support Provider support for overlay, make it easy to build toast and In-App notification. this library support ALL platform Interaction If yo

Bin 340 Jan 1, 2023
A Flutter package which provides helper widgets for selecting single or multiple account/user from the given list.

account_selector A Flutter package which provides helper widgets for selecting single or multiple account/user from a list Supported Dart Versions Dar

Harpreet Singh 49 Oct 7, 2021
A custom Slider which accepts a list of ordered values.

MultiSlider A custom Slider which accepts a list of ordered values. It's meant to be as simple as the original Slider! UI with it Usages Continuous sl

Sthefano Schiavon 7 Dec 3, 2022
A widget that can be dragged and scrolled in a single gesture and snapped to a list of extents.

Sliding Sheet A widget that can be dragged and scrolled in a single gesture and snapped to a list of extents. Click here to view the full example. Ins

null 396 Mar 10, 2022
Donation/Support buttons to allow you to add your favorite support buttons like: Paypal, Ko-fi or Patreon and more.

flutter_donation_buttons Donation/Support buttons to allow you to add your favorite support buttons like: Paypal, Ko-fi or Patreon and more. Getting S

null 6 Dec 10, 2022
A Redux version tailored for Flutter, which is easy to learn, to use, to test, and has no boilerplate

A Redux version tailored for Flutter, which is easy to learn, to use, to test, and has no boilerplate. Allows for both sync and async reducers.

Marcelo Glasberg 214 Dec 13, 2022
Widget to let the user search through a keyword string typed on a customizable keyboard in a single or multiple choices list presented as a dropdown in a dialog box or a menu.

searchable_dropdown Widget to let the user search through a keyword string typed on a customizable keyboard in a single or multiple choices list prese

Bobby Stenly Irawan 108 Sep 11, 2022
PowerFileView - A powerful file view widget, support a variety of file types, such as Doc Eexcl PPT TXT PDF and so on, Android is implemented by Tencent X5, iOS is implemented by WKWebView.

PowerFileView - A powerful file view widget, support a variety of file types, such as Doc Eexcl PPT TXT PDF and so on, Android is implemented by Tencent X5, iOS is implemented by WKWebView.

Yao 8 Oct 22, 2022
A sliding up panel widget which can be used to show or hide content, beautiful and simple.

flutter_sliding_up_panel A sliding up panel widget which can be used to show or hide content, beautiful and simple. demo Getting Started dependencies:

null 25 Dec 12, 2022
An alternative to Overlay which allows you to easily render and hit test a widget outside its parent bounds

An alternative to Overlay which allows you to easily render and hit test a widget outside its parent bounds. Based on the original idea by @shrouxm he

gskinner team 26 Dec 31, 2022
A Flutter widget which synchronize a ScrollView and a custom tab view

scrollable_list_tabview A Flutter widget which synchronize a ScrollView and a custom tab view. The main idea is to create a custom tab view synchroniz

Aswanath C K 0 Apr 12, 2022
A popup simple topModalSheet menu button widget with handsome design and easy to use

top_modal_sheet A popup simple topModalSheet menu button widget with handsome design and easy to use. Installations Add top_modal_sheet: ^1.0.0 in you

Baldemar Alejandres 5 Jul 29, 2022
Flutter ColorFilter generator and presets to use with ColorFiltered widget.

Flutter ColorFilter generator and presets to use with ColorFiltered widget.

null 2 Jun 7, 2022