Flutter 实现下拉刷新和上拉加载
flutter 实现 加载 刷新
2023-09-14 09:04:29 时间
参考
Flutter下拉刷新和上拉加载更多
下拉刷新
上拉加载更多
下拉刷新直接用flutter自带的控件RefreshIndicator组件即可,上拉加载可以通过ListView 中的ScrollController 属性,根据 ListView 的位置来判断是否滑动到了底部来做加载更多的处理
下面用们用到的json数据接口为:https://jsonplaceholder.typicode.com/posts/1/comments
下拉刷新
就是在我们上一节讲到的解析的列表外面嵌套一个RefreshIndicator,然后通过onRefresh进行监听
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("请求数据 Dio Demo"),
),
body: this._list.length > 0
? RefreshIndicator(
onRefresh: _onRefresh,
child: ListView.builder(
itemCount: this._list.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_list[index]["email"], maxLines: 1),
));
}))
: Text("加载中..."));
}
Future<void> _onRefresh() async {
print('执行刷新');
_getData();
await Future.delayed(Duration(seconds: 3), () {
print('refresh');
});
}
_getData() async {
var apiUrl = "https://jsonplaceholder.typicode.com/posts/${_page}/comments";
Response result = await Dio().get(apiUrl);
setState(() {
_list.addAll(result.data);
_page++;
});
print("获取数据操作");
}
上拉加载更多
通过ListView 中的ScrollController 属性,根据 ListView 的位置来判断是否滑动到了底部来做加载更多的处理
_scrollController.position.pixels 滚动的距离
_scrollController.position.maxScrollExtent 总距离
自定义下部加载的控件
Widget _getMoreWidget() {
return Center(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'加载中...',
style: TextStyle(fontSize: 16.0),
),
CircularProgressIndicator(
strokeWidth: 1.0,
)
],
),
),
);
}
ScrollController _scrollController = ScrollController(); //listview 的控制器
List _list = [];
int _page = 1;
bool isLoading = false;
@override
void initState() {
super.initState();
_getData();
//监听划到最底部就进行if内的操作
_scrollController.addListener(() {
if (_scrollController.position.pixels >
_scrollController.position.maxScrollExtent - 20) {
print('滑动到了最底部');
_getData();
}
});
}
ListView.builder(
itemCount: _list.length,
controller: _scrollController,
itemBuilder: (context, index) {
if (index == _list.length - 1) {
return Column(
children: <Widget>[
ListTile(
title: Text(_list[index]["email"], maxLines: 1),
),
Divider(),
//如果条目达到最底部,则还要展示一个加载圈
_getMoreWidget()
],
);
} else {
//没有到达底部直接加载条目
return Column(
children: <Widget>[
ListTile(
title: Text(_list[index]["email"], maxLines: 1),
),
Divider()
],
);
}
}))
代码:
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables, avoid_print, prefer_is_empty, slash_for_doc_comments, unnecessary_brace_in_string_interps, prefer_const_constructors_in_immutables, prefer_final_fields
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
class LoadMorePage extends StatefulWidget {
LoadMorePage({Key? key}) : super(key: key);
@override
_LoadMorePageState createState() => _LoadMorePageState();
}
class _LoadMorePageState extends State<LoadMorePage> {
ScrollController _scrollController = ScrollController(); //listview 的控制器
List _list = [];
int _page = 1;
bool isLoading = false;
var json; //是否正在加载数据
@override
void initState() {
super.initState();
//之所以写三遍是因为我发现接口中每一页数据较少,第一次加载一页达不到底部,监听不到滑动
_getData();
_getData();
_getData();
print("到达了最底部。。。");
//下面这个方法每次都底部都会执行,上面的代码只会执行一次
_scrollController.addListener(() {
if (_scrollController.position.pixels >
_scrollController.position.maxScrollExtent - 20) {
print('滑动到了最底部');
_getData();
}
});
}
_getData() async {
var apiUrl =
"https://jsonplaceholder.typicode.com/posts/${_page}/comments";
Response result = await Dio().get(apiUrl);
// print(json.decode(result.data)["result"]);
setState(() {
_list.addAll(result.data);
_page++;
});
}
/**
* 加载更多时显示的组件,给用户提示
*/
Widget _getMoreWidget() {
return Center(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'加载中...',
style: TextStyle(fontSize: 16.0),
),
CircularProgressIndicator(
strokeWidth: 1.0,
)
],
),
),
);
}
Future<void> _onRefresh() async {
print('执行刷新');
// this._getData();
await Future.delayed(Duration(seconds: 3), () {
print('refresh');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("请求数据"),
),
body: _list.length > 0
? RefreshIndicator(
onRefresh: _onRefresh,
child: ListView.builder(
itemCount: _list.length,
controller: _scrollController,
itemBuilder: (context, index) {
if (index == _list.length - 1) {
return Column(
children: <Widget>[
ListTile(
title:
Text(_list[index]["email"], maxLines: 1),
),
Divider(),
//如果条目达到最底部,则还要展示一个加载圈
_getMoreWidget()
],
);
} else {
//没有到达底部直接加载条目
return Column(
children: <Widget>[
ListTile(
title:
Text(_list[index]["email"], maxLines: 1),
),
Divider()
],
);
}
}))
: _getMoreWidget());
}
}
相关文章
- Flutter之网络请求封装
- Flutter使用Canvas实现微信红包领取效果
- 重走Flutter状态管理之路—Riverpod最终篇
- Flutter 实战快速实现音视频通话应用
- Flutter一步实现Toast 弹窗(fluttertoast 库)
- Flutter 下载器 | flutter_download_manager源码解析
- Flutter混编工程之打通纹理之路
- Flutter 环境配置及运行示例程序
- 使用Flutter_Redux实现主题切换
- Flutter 知识集锦 | 基于 Flow 实现滑动显隐层
- 【Flutter】Dart 面向对象 ( 抽象类 | 抽象方法 )
- 【Flutter】Flutter 项目中使用 Flutter 插件 ( Flutter 插件管理平台 | 搜索 Flutter 插件 | 安装 Flutter 插件 | 使用 Flutter 插件 )
- 【错误记录】Flutter 报错 ( Could not resolve io.flutter:flutter_embedding_debug:1.0.0. )
- 【Flutter】Flutter Gallery 官方示例简介 ( 项目简介 | 工程构建 )
- 【Flutter】顶部导航栏实现 ( Scaffold | DefaultTabController | TabBar | Tab | TabBarView )
- 【Flutter】HTTP 网络操作 ( 引入 http 插件 | 测试网站 | Get 请求 | Post 请求 | 将响应结果转为 Dart 对象 | Future 异步调用 )
- 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 EventChannel 通信 )
- 玩过Tauri和Electron,最终我选择Flutter
- flutter系列之:如何自定义动画路由