This is a repository to create a minimal reproducible example.

I want SliverAppBar hidden when ScrollablePositionedList.builder is Scrolled. This is the relevant piece of code I am including here.

          NestedScrollView(
              headerSliverBuilder: (context, innerBoxIsScrolled) => [
                    SliverAppBar(
                      backgroundColor: Colors.blue,
                      expandedHeight: 112,
                      snap: true,
                      pinned: false,
                      floating: true,
                      forceElevated: true,
                      actions: <Widget>[
                        IconButton(
                          icon: Icon(Icons.event),
                        )
                      ],
                      flexibleSpace: SafeArea(
                        child: Column(
                          children: <Widget>[
                            Container(
                              height: kToolbarHeight,
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.center,
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: <Widget>[
                                  Text(
                                    'Title',
                                    style: Theme.of(context)
                                        .textTheme
                                        .title
                                        .copyWith(
                                            fontSize: 16, color: Colors.white),
                                  ),
                                  SizedBox(
                                    height: 2,
                                  ),
                                  Text(
                                    'Date',
                                    style: Theme.of(context)
                                        .textTheme
                                        .caption
                                        .copyWith(
                                            fontSize: 10, color: Colors.white),
                                  ),
                                  SizedBox(
                                    height: 2,
                                  ),
                                  Text(
                                    'Another Text',
                                    style: Theme.of(context)
                                        .textTheme
                                        .subtitle
                                        .copyWith(
                                            fontSize: 14, color: Colors.white),
                                  ),
                                ],
                              ),
                            ),
                            Expanded(
                              child: Container(
                                height: kToolbarHeight,
                                width: MediaQuery.of(context).size.width,
                                color: Colors.white,
                                child: Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceEvenly,
                                  children: <Widget>[
                                    Text(
                                      'Prev',
                                    ),
                                    Text(
                                      'Next',
                                    )
                                  ],
                                ),
                              ),
                            )
                          ],
                        ),
                      ),
                    )
                  ],
              body: ScrollablePositionedList.builder(
                  physics: ScrollPhysics(),
                  itemPositionsListener: itemPositionListener,
                  itemScrollController: _itemScrollController,
                  initialScrollIndex: 0,
                  itemCount: 500,
                  itemBuilder: (BuildContext ctxt, int index) {
                    return Container(
                        margin: EdgeInsets.all(16)
                        ,
                        child: Text('$index'));
                  })),

I tried two approaches so far none of them working properly,

Approach 1

I added physics: ScrollPhysics(), to ScrollablePositionedList.builder

Output:

enter image description here

Appraoch 2

I added physics: NeverScrollableScrollPhysics(), to ScrollablePositionedList.builder

SliverAppBar hides this time but now I can not scroll to the very end of ScrollablePositionedList.builder I have 500 items on my list but it scrolls up to only 14th item, see the output. Also, it lags too much on scroll

Output:

enter image description here

Thanks in advance.


Solution 1: Ravinder Kumar

Answering question myself

This problem has no solution for it. I have created an issue here

It looks like ScrollablePositionedList with SliverAppBar cannot work until Flutter Team does not add shrinkwrap property to ScrollablePositionedList.

Feature request to add shrinkwrap is created here


Solution 2: vinod kumar

    It works for me
//create list of global keys

 List&lt;GlobalKey&gt; _formKeys = [];

//assign keys from your list

for(int i=0 ;i&lt; syourlist.length;i++){
final key = GlobalKey();
_formKeys.add(key);
}

//in list view give key as below

key:_formKeys[index]

//on button click

 Scrollable.ensureVisible(_formKeys[index].currentContext);


Solution 3: Kdon

Here is a basic workaround:

  • Use the ItemsPositionsListener to listen for the current item the list has scrolled to.
  • Then create boolean values to check the scroll-direction and amount.
  • These conditions control an AnimatedContainer controlling the height of a custom header.
  • This is placed as a child in a Column with the header in a Flexible widget so the scrollablelist correctly takes up the space before and after animation.

Although this is very basic and does not use the NestedScrollView, it keeps use of the ScrollablePositionedList, and achieves a similar effect with a header that slides in and out, based on the set scroll conditions.

Providing in case helps anyone else, until the underlying issue is fixed...:)


import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

class ScrollAllWords extends StatefulWidget {
  const ScrollAllWords({
    Key? key,
    required this.list,
  }) : super(key: key);

  final List<String> list;

  @override
  State<ScrollAllWords> createState() => _ScrollAllWordsState();
}

class _ScrollAllWordsState extends State<ScrollAllWords> {

/// use this listener to control the header position.
  final _itemPositionsListener = ItemPositionsListener.create();

///Can also use the ItemScrollController to animate through the list (code omitted)
final _itemScrollController = ItemScrollController();

  /// Gets the current index the list has scrolled to.
  int _currentIndex = 0;

  /// Compares against current index to determine the scroll direction.
  int _shadowIndex = 0;

  bool _reverseScrolling = false;
  bool _showHeader = true;

  @override
  void initState() {

    /// Set up the listener.
    _itemPositionsListener.itemPositions.addListener(() {
      checkScroll();
    });

    super.initState();
  }

  void checkScroll() {
    /// Gets the current index of the scroll.
    _currentIndex =
        _itemPositionsListener.itemPositions.value
            .elementAt(0)
            .index;

    /// Checks the scroll direction.
    if (_currentIndex > _shadowIndex) {
      _reverseScrolling = false;
      _shadowIndex = _currentIndex;
    }
    if (_currentIndex < _shadowIndex) {
      _reverseScrolling = true;
      _shadowIndex = _currentIndex;
    }

    /// Checks whether to show or hide the scroller (e.g. show when scrolled passed 15 items and not reversing).
    if (!_reverseScrolling && _currentIndex > 15) {
      _showHeader = false;
    } else {
      _showHeader = true;
    }

    setState(() {});
  }

  @override
  Widget build(BuildContext context) {

    return Column(
      children: [
        AnimatedContainer(
          duration: const Duration(milliseconds: 120),
          height: _showHeader ? 200 : 0,
          curve: Curves.easeOutCubic,

          child: Container(
            color: Colors.red,
            height: size.height * 0.20,
          ),
        ),

        Flexible(
          child: ScrollablePositionedList.builder(
            itemScrollController: _itemScrollController,
            itemPositionsListener: _itemPositionsListener,
            itemCount: widget.list.length,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text(widget.list[index]),
              );
            },
          ),
        ),

      ],
    );
  }
}

Example