Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refresh indicator doesn't work when list doesn't fill the whole page

Tags:

flutter

dart

I have a page the has a list with refresh indicator. When I have many elements in the list (filling the whole view and more, i.e. I can scroll), the refresh indicator works. However, when I have only one or two elements in the list (nothing to scroll), then the refresh indicator doesn't work. Is this the expected behaviour? Is there a way to get the indicator to work also for short lists?

I tried wrapping the list view (child of refresh indicator) with a scroll bar but the problem still persists.


Future<void> _onRefresh() async {
    _getPeople();
  }


@override
  Widget build(BuildContext context) {
    super.build(context);
    return new Container(
      child: _items.length == 0
          ? Center(child: CircularProgressIndicator())
          : new RefreshIndicator(
              onRefresh: _onRefresh,
              child: Scrollbar(
                child: new ListView.builder(
                  controller: controller,
                  itemBuilder: (context, index) {
                    return PeopleCard(
                      People: _items[index],
                      source: 2,
                    );
                  },
                  itemCount: _items.length,
                ),
              )),
    );
  }

If the length of the items list is 1 or 2 or any amount that doesn't need scrolling, refresh indicator should also work.

like image 707
juloz Avatar asked Aug 16 '19 06:08

juloz


4 Answers

Set the physics to AlwaysScrollableScrollPhysics just like the below code.

new RefreshIndicator(
    key: _refreshIndicatorKey,
    color: Colors.blue,
    onRefresh: (){
        setState(() {
            _future = fetchPosts(http.Client()); 
            _getAvalailableSlots();
        });
    },
    child: ListView.builder(
        physics: AlwaysScrollableScrollPhysics(),
        itemCount: data.length,
        itemBuilder: (context, i) {
            //do something
        }
    )
)
like image 62
Ali Bacelonia Avatar answered Oct 22 '22 17:10

Ali Bacelonia


To make RefreshIndicator always appear, set physics: const AlwaysScrollableScrollPhysics() for the scrollable child like below.

ListView(     physics: const AlwaysScrollableScrollPhysics(),     children: <Widget>[widget.bodyWidget] ) 

If you still have some errors, the below might help.

  • ListView widget needs to have height value to be "always" scrollable vertically. So wrap it with SizedBox or some other proper widget and set the height.
  • How to fix the height? Get the height of viewport using MediaQuery.of(context).size.height and, if needed, subtract the value of non-scrollable part.
  • If you use SingleChildScrollView and it's not working with AlwaysScrollableScrollPhysics(), it is because the child doesn't have height. fix the child's height or just use ListView.

To sum up, the following worked for me.

sizes.bottomNavigationBar and sizes.appBar are the constant variables I made to customize the appbar and navbar.

RefreshIndicator(     onRefresh: widget.onRefresh,     child: SizedBox(         height: MediaQuery.of(context).size.height -                 sizes.bottomNavigationBar -                 sizes.appBar,         child: ListView(             physics: const AlwaysScrollableScrollPhysics(),             children: <Widget>[widget.bodyWidget]     )), ) 

If you're finding any reliability, Refresh indicator does not show up part of the official doc would help.

like image 23
Yujin Choi Avatar answered Sep 30 '22 04:09

Yujin Choi


Case 1:

Use AlwaysScrollableScrollPhysics() in your Listview or SingleChildScrollView.

physics: const AlwaysScrollableScrollPhysics(),

Case 2:

If you want to use other scroll physics, use this way...

physics: BouncingScrollPhysics(
 parent: AlwaysScrollableScrollPhysics(),
),

Case 3:

Make sure you didn't make shrinkWrap, true. ShrinkWrap has to be false like default.

shrinkWrap: true. ❌

shrinkWrap: false. ✅

shrinkWrap: false,

Case 4:

If you have any custom widgets other than a listview, use stack and listview this way...

     RefreshIndicator(
      onRefresh: () async {
        print('refreshing');
      },
      Stack(
        children: [
          YourWidget(),
          ListView(
            physics: const AlwaysScrollableScrollPhysics(),
          ),
        ],
      ),
     ),
like image 14
motasimfuad Avatar answered Oct 22 '22 16:10

motasimfuad


To use with BouncingScrollPhysics:

 RefreshIndicator(
              onRefresh: () async {
              
              },
              child: ListView.builder(
                  physics: BouncingScrollPhysics(
                      parent: AlwaysScrollableScrollPhysics()),
                  itemBuilder: (context, index) {
                    return Text("${index}");
                   }),
like image 3
Hamdam Muqimov Avatar answered Oct 22 '22 16:10

Hamdam Muqimov