Reputation: 8531
I have a page in my app with a ListView. I'm using a StreamBuilder to receive data. When there is data I build the listview children and the listview is wrapped inside a RefreshIndicator. This is working fine.
Now I want to handle the situation when there is no data aka EmptyState. Be able to display a Container with some content, while still be able to support pull to refresh to force the page/Listview to check for data.
This is how I'm currently doing it
return RefreshIndicator(
key: upcomingRefreshIndicatorKey,
onRefresh: handleRefresh,
child: snapshot.hasData ? list : Stack(children: <Widget>[list, emptystate],) ,
);
I'm not sure this is the way to handle EmptyState with ListView, but so far this is the only way I can see to still support refresh when the list is empty. So my main question is how you best handle empty state with LIstView and still supporting PullToRefresh?
Upvotes: 3
Views: 9825
Reputation: 9775
To support the RefreshIndicator inside an empty ListView you can set physics: AlwaysScrollableScrollPhysics()
. This makes the ListView
always scrolalble. Therefore, we can always trigger the RefreshIndicator
.
The Container
you want to display when the ListView
is empty can be accomplished by two methods:
ListView
with a SingleChildScrollView with physics
set to AlwaysScrollableScrollPhysics()
. Then you can place your Container
as the child of the SingleChildScrollView
.ListView
you can simply replace the children with your Container
, given your data is empty (or null).In the follwing standalone example, I took the second approach:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
// dummy stream
StreamController<List<String>> yourStream = StreamController<List<String>>();
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: RefreshIndicator(
onRefresh: refresh,
child: StreamBuilder<List<String>>(
stream: yourStream.stream,
builder: (_, snapshot) => ListView(
physics: AlwaysScrollableScrollPhysics(), // This makes it always scrollable!
children: snapshot.data == null
? [Text('Nothing here :(')]
: snapshot.data
.map((text) => ListTile(
title: Text(text),
))
.toList()),
),
),
),
),
);
}
Future<void> refresh() {
// dummy code
yourStream.add(['Quick', 'Brown', 'Fox']);
return Future.value();
}
}
Upvotes: 18