Home > Enterprise >  Make RefreshIndicator work on whole screen (ListView)
Make RefreshIndicator work on whole screen (ListView)

Time:11-01

While looking for solutions, i found some related discussions, but none of the solutions worked in my case.

I made a "RefreshableScrollFrame" widget in my app, which offers a generic frame for pages that should show a StatusBar (loading indicator, etc.) and which should provide pull-down to refresh.

RefreshableScrollFrame

return Center(
      child: Column(
        children: [
          SizedBox(
            height: 4,
            child: const MyStatusbarWidget(),
          ),
          RefreshIndicator(
            onRefresh: onRefresh,
            child: SingleChildScrollView(
              physics: const AlwaysScrollableScrollPhysics(),
              child: child,
            ),
          )
        ],
      ),
    );

Child Option - ListView:

ListView.builder(
            itemCount: items.length,
            physics: const NeverScrollableScrollPhysics(),
            shrinkWrap: true,
            itemBuilder: (context, i) => Card(
              child: ListTile(
                 title: Text(items[i].name),
              ),
            ),
          );

Child Option - Column with listview and static items:

Column(
          children: [
            ListView.builder(
                itemCount: items.length,
                physics: const NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemBuilder: (context, i) => Card(
                  child: ListTile(
                    title: Text(items[i].name),
                  ),
                ),
              ),
            ...someStaticWidgets,
          ],
        );

So far so good, everything works fine, except one important detail. The RefreshIndicator is only triggered in areas, which are covered by the child widget. If the content is small and covers just the top of the page, the gesture is detected only in that area. If the content is just an empty ListView, i won't even be able to trigger a refresh.

I tried several suggested solutions in order to "expand" the child to the whole screen, but i always ran into exceptions, when trying to get rid of shrinkWrap, or when adding Expanded() and so on.

Any hints would be appreciated.

CodePudding user response:

you have to wrap the whole body of your scaffold with refreshIndicator not a portion of it.

CodePudding user response:

I found a solution that seems to work for me, using a LayoutBuilder ConstrainedBox to wrap the contents of the SingleChildScrollView. This way, the SingleChildScrollView will always span the whole remaining space.

return Column(
  children: [
    const SizedBox(
      height: 4,
      child: MyStatusbarWidget(),
    ),
    Expanded(
      child: LayoutBuilder(builder: (context, constraints) {
        return RefreshIndicator(
          onRefresh: onRefresh,
          child: SingleChildScrollView(
            physics: const AlwaysScrollableScrollPhysics(),
            child: SizedBox(
              height: constraints.maxHeight,
              child: child,
            ),
          ),
        );
      }),
    ),
  ],
);
  • Related