下拉刷新或(滑动刷新)功能使用户能够下拉以获取更多数据。在许多现代应用程序中都可以看到下拉刷新功能。可以在可滚动的组件中实现下拉刷新功能。
在本文中,我们将在Flutter实现此功能。如果您不熟悉flutter,请在深入阅读本文之前访问flutter.dev。 Flutter是关于小部件的, flutter的一切都只是小部件。 Flutter还提供了一个小部件来实现此功能以及即RefreshIndicator。
RefreshIndicator:当孩子的Scrollable后代overscrolls 时,动画圆形进度指示器淡入视图。当滚动结束时,如果指标已被拖到足够远使其变得完全不透明,则调用onRefresh回调。回调预计会更新可滚动的内容,然后完成它返回的 Future。回调的 Future 完成后刷新指示器消失。
要创建flutter应用程序,请打开终端/命令并运行以下命令:
flutter create app_name
// app_name should be the name of your app
Example:
flutter create demo_app
运行此命令后,您应该有一个指定app_name的文件夹。导航到该文件夹并打开lib/main。dart文件。
Note: In order to implement pull-to-refresh feature we are not going to use any other dependencies.
要创建 RefreshIndicator,请使用以下语法:
RefreshIndicator(
child: ...
onRefresh: ...
)
These are required fields.
child: Should be a scrollable widget
onRefresh: A function that should return a future.
Future is a type in dart.
我们将逐步实现这一点。
第 1 步:如上所述,为了使 RefreshIndicator 正常工作,我们将需要一个可滚动组件。为此,我们将使用 ListView。在这一步中,我们将为我们的应用程序定义一些演示数据。
Dart
// Local State to display items in listview
List _demoData;
// This method will run once widget is loaded
// i.e when widget is mounting
@override
void initState() {
// initializing state / demo data
_demoData = [
"Flutter",
"React Native",
"Cordova/ PhoneGap",
"Native Script"
];
super.initState();
}
Dart
... some code
ListView.builder(
itemBuilder: (ctx, idx) {
// List Item
return Card(
child: ListTile(
title: Text(_demoData[idx]),
),
);
},
// Length of the list
itemCount: _demoData.length,
// To make listView scrollable
// even if there is only a single item.
physics: const AlwaysScrollableScrollPhysics(),
)
... some code
Dart
... some code
RefreshIndicator(
child: ListView.builder(
itemBuilder: (ctx, idx) {
// List Item
return Card(
child: ListTile(
title: Text(_demoData[idx]),
),
);
},
// Length of the list
itemCount: _demoData.length,
// To make listView scrollable
// even if there is only a single item.
physics: const AlwaysScrollableScrollPhysics(),
),
// Function that will be called when
// user pulls the ListView downward
onRefresh: () {
return Future.delayed(
Duration(seconds: 1),
() {
/// adding elements in list after [1 seconds] delay
/// to mimic network call
///
/// Remember: setState is necessary so that
/// build method will run again otherwise
/// list will not show all elements
setState(() {
_demoData.addAll(["Ionic", "Xamarin"]);
});
// showing snackbar
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: const Text('Page Refreshed'),
),
);
},
);
},
)
... some code
Dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GeeksforGeeks',
// to hide debug banner
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.green,
),
home: HomePage(),
);
}
}
/// [StatefulWidget] so that we can change
/// internal state to show proper working
/// of [PULL TO REFRESH] feature
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
// ScaffoldKey object. This is required
// to show snackbar
// This is optional. This is not required always
GlobalKey _scaffoldKey;
// Local State to display items in listview
List _demoData;
// This method will run once widget is loaded
// i.e when widget is mounting
@override
void initState() {
// initializing states
_demoData = [
"Flutter",
"React Native",
"Cordova/ PhoneGap",
"Native Script"
];
_scaffoldKey = GlobalKey();
super.initState();
}
// This method will run when widget is unmounting
@override
void dispose() {
// disposing states
_scaffoldKey?.currentState?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text('GeeksforGeeks'),
),
// Widget to show RefreshIndicator
body: RefreshIndicator(
child: ListView.builder(
itemBuilder: (ctx, idx) {
// List Item
return Card(
child: ListTile(
title: Text(_demoData[idx]),
),
);
},
// Length of the list
itemCount: _demoData.length,
// To make listView scrollable
// even if there is only a single item.
physics: const AlwaysScrollableScrollPhysics(),
),
// Function that will be called when
// user pulls the ListView downward
onRefresh: () {
return Future.delayed(
Duration(seconds: 1),
() {
/// adding elements in list after [1 seconds] delay
/// to mimic network call
///
/// Remember: [setState] is necessary so that
/// build method will run again otherwise
/// list will not show all elements
setState(() {
_demoData.addAll(["Ionic", "Xamarin"]);
});
// showing snackbar
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: const Text('Page Refreshed'),
),
);
},
);
},
),
),
);
}
}
第 2 步:我们将使用 ListItem 和 AlwaysScrollingPhysics 创建我们的 ListView。
Dart
... some code
ListView.builder(
itemBuilder: (ctx, idx) {
// List Item
return Card(
child: ListTile(
title: Text(_demoData[idx]),
),
);
},
// Length of the list
itemCount: _demoData.length,
// To make listView scrollable
// even if there is only a single item.
physics: const AlwaysScrollableScrollPhysics(),
)
... some code
第 3 步:最后将 ListView 包装到 RefreshIndicator 中以使用下拉刷新功能。
Dart
... some code
RefreshIndicator(
child: ListView.builder(
itemBuilder: (ctx, idx) {
// List Item
return Card(
child: ListTile(
title: Text(_demoData[idx]),
),
);
},
// Length of the list
itemCount: _demoData.length,
// To make listView scrollable
// even if there is only a single item.
physics: const AlwaysScrollableScrollPhysics(),
),
// Function that will be called when
// user pulls the ListView downward
onRefresh: () {
return Future.delayed(
Duration(seconds: 1),
() {
/// adding elements in list after [1 seconds] delay
/// to mimic network call
///
/// Remember: setState is necessary so that
/// build method will run again otherwise
/// list will not show all elements
setState(() {
_demoData.addAll(["Ionic", "Xamarin"]);
});
// showing snackbar
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: const Text('Page Refreshed'),
),
);
},
);
},
)
... some code
完整的源代码:
Dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GeeksforGeeks',
// to hide debug banner
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.green,
),
home: HomePage(),
);
}
}
/// [StatefulWidget] so that we can change
/// internal state to show proper working
/// of [PULL TO REFRESH] feature
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State {
// ScaffoldKey object. This is required
// to show snackbar
// This is optional. This is not required always
GlobalKey _scaffoldKey;
// Local State to display items in listview
List _demoData;
// This method will run once widget is loaded
// i.e when widget is mounting
@override
void initState() {
// initializing states
_demoData = [
"Flutter",
"React Native",
"Cordova/ PhoneGap",
"Native Script"
];
_scaffoldKey = GlobalKey();
super.initState();
}
// This method will run when widget is unmounting
@override
void dispose() {
// disposing states
_scaffoldKey?.currentState?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text('GeeksforGeeks'),
),
// Widget to show RefreshIndicator
body: RefreshIndicator(
child: ListView.builder(
itemBuilder: (ctx, idx) {
// List Item
return Card(
child: ListTile(
title: Text(_demoData[idx]),
),
);
},
// Length of the list
itemCount: _demoData.length,
// To make listView scrollable
// even if there is only a single item.
physics: const AlwaysScrollableScrollPhysics(),
),
// Function that will be called when
// user pulls the ListView downward
onRefresh: () {
return Future.delayed(
Duration(seconds: 1),
() {
/// adding elements in list after [1 seconds] delay
/// to mimic network call
///
/// Remember: [setState] is necessary so that
/// build method will run again otherwise
/// list will not show all elements
setState(() {
_demoData.addAll(["Ionic", "Xamarin"]);
});
// showing snackbar
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: const Text('Page Refreshed'),
),
);
},
);
},
),
),
);
}
}
Note: In some cases, you will notice that the refresh indicator is not showing.
To make it visible all the time please use physics: In Flutter all the scrollable
widgets have physics properties.
即使列表中只有几个元素,以下内容也将启用滚动。
ListView(
physics: const AlwaysScrollableScrollPhysics(),
...
)
输出: