60

I added the RefreshIndicator to my page, but there is no indicator visible when pull to refresh. The code is below:

class HomePage extends StatefulWidget {
  HomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<HomePage> {

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: LocalGalleryTab(),
    );
  }
}

class LocalGalleryTab extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _LocalGalleryState();
  }
}

class _LocalGalleryState extends State<LocalGalleryTab> {
  @override
  Widget build(BuildContext context) {
    return new Container(child: new Center(
      child: new RefreshIndicator(
        child: Text("Local Gallery"),
        onRefresh: _refreshLocalGallery,
      ),
    ));
  }

  Future<Null> _refreshLocalGallery() async{
    print('refreshing stocks...');

  }
}

How to use the RefreshIndicator? The flutter doc does not give much infomation.

mianlaoshu
  • 2,342
  • 3
  • 27
  • 48

12 Answers12

62

By design, RefreshIndicator works with ListView.

But if you want to use RefreshIndicator with non-scrollable-widgets, you can wrap your widget into Stack with ListView:

RefreshIndicator(
  onRefresh: () {},
  child: Stack(
    children: <Widget>[ListView(), YOUR_CHILD_WIDGET],
  ),
),
Pavel Shorokhov
  • 4,485
  • 1
  • 35
  • 44
ahmed khattab
  • 2,311
  • 3
  • 16
  • 30
62

Refresh Indicator by default does not work on a short list so add the following to the ListView.builder

physics: const AlwaysScrollableScrollPhysics(),
Venkatesh A
  • 1,875
  • 1
  • 19
  • 23
35

You need to add scroll child inside RefreshIndicator see example below

enter image description here

class HomePage extends StatefulWidget {
  HomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<HomePage> {

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: LocalGalleryTab(),
    );
  }
}

class LocalGalleryTab extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _LocalGalleryState();
  }
}

class _LocalGalleryState extends State<LocalGalleryTab> {
  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
        child: ListView(
          children: List.generate(50,  (f) => Text("Item $f")),
        ),
        onRefresh: _refreshLocalGallery,
      );
  }

  Future<Null> _refreshLocalGallery() async{
    print('refreshing stocks...');

  }
}
Ahmad Khan
  • 757
  • 9
  • 22
Ahmed
  • 2,221
  • 14
  • 18
  • 2
    its not working on ListView.builder! Any alternatives? – abrsh May 19 '20 at 20:04
  • 4
    Just to add to this: The refresh indicator might not work when items occupy height less than the parent height. This is due to since the scrolling isn't allowed when the items occupy less space than parent and refresh Indicator allows refresh only when the child allows scrolling. Check @Paresh Mangukiya's answer – Nikhileshwar Dec 24 '20 at 11:55
17
RefreshIndicator(
   onRefresh: _onRefresh,
   child:SingleChildScrollView(
   physics: AlwaysScrollableScrollPhysics(),
   child: ListView(
   padding: EdgeInsets.all(8.0),

   children: _listData.map((i) {
    return ListTile(
      title: Text("Item $i"),
    );
  }).toList(),
 )
)
);

Add physics in SingleChildScrollView

ouflak
  • 2,458
  • 10
  • 44
  • 49
Amit Jajoo
  • 220
  • 3
  • 7
2

You can use ListView with SinglchildScrollView widget also.

    RefreshIndicator(
      onRefresh: () {
         //HERE YOUR FUNCTION TO CALL
      },
      child: Stack(
        children: <Widget>[
              ListView(
                physics: const AlwaysScrollableScrollPhysics(),
                 children: []
                )
              ],
            ),
        ),
M E S A B O
  • 783
  • 1
  • 11
  • 15
  • 1
    Work for me after using physics: const AlwaysScrollableScrollPhysics(), in ListView – Miko Aug 03 '22 at 10:10
2

I got the solution of this after little change from one answer which was already there in current page! Just need to change position of stack children (main widget first then listview).

updated answer which will work 100%:

RefreshIndicator(
      onRefresh: () {},
      child: Stack(
        children: <Widget>[YOUR_CHILD_WIDGET, ListView()],
      ),
    ),

past answer from above answers:

RefreshIndicator(
  onRefresh: () {},
  child: Stack(
    children: <Widget>[ListView(), YOUR_CHILD_WIDGET],
  ),
),
Deven
  • 684
  • 7
  • 10
1

In Non-scrollable list view, RefreshIndicator does not work, so you have to wrap your widget with Stack for implementing pull down to refresh.

RefreshIndicator(
  onRefresh: () {
  // Refresh Functionality 
  },
  child: Stack(
            children: [
              ListView(
                padding: EdgeInsets.zero,
                shrinkWrap: true,
                children: [
                  SizedBox(
                    height: MediaQuery.of(context).size.height,
                  )
                ],
              ),
              // Your Widget 
            ],
          );
        ),
Tarun Sharma
  • 914
  • 9
  • 15
1

The most important is to implement in ListView:

physics: const AlwaysScrollableScrollPhysics(),

because otherwise items which are not covering whole screen are stuck and you cannot move/refresh them.

RobEleven
  • 29
  • 3
0

I think the best approach by far is to use CustomScrollView with RefreshIndicator. See example below.

class RefreshDemo extends StatelessWidget {
  const RefreshDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: () async {
        // Your refresh logic goes here
        await Future.delayed(Duration(seconds: 2));
        return true;
      },
      child: CustomScrollView(
        slivers: [
          // Wrap your widgets with the SliverToBoxAdapter
          SliverToBoxAdapter(
            child: Container(
              child: Column(
                children: [
                  Text('Hello'),
                  Text('World'),
                
                ]
              )
            ),
          ),
        ],
      ),
    );
  }
}
paulobunga
  • 277
  • 6
  • 13
0

RefreshIndicator works with ListView..

RefreshIndicator(
    onRefresh: () {},
    child: ListView.builder(
        itemCount: 1, //just to build the Widget once..
        itemBuilder:(context, index) => //your Widget..
    )
)
0

Always make sure that you are not using BouncingScrollPhysics() in Listview as it does not allow to refresh.

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/34563327) – Jeremie Jun 22 '23 at 22:04
-1

as mentioned above refresh indicator only works with Listview so use it else wrap Listview with Stack

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – lepsch Jun 19 '22 at 10:05