关于Flutter下拉刷新和上拉分页
在Flutter官方sdk中给我们提供了下拉刷新的组件RefreshIndicator。但是没有提供上拉分页加载更多的组件。但是在Flutter ListView中有一个ScrollController属性,它就是专门来控制ListView滑动事件,在这里我们可以根据ListView的位置来判断是否滑动到了底部来做加载更多的处理。
教程涉及Api接口:
https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1
Flutter RefreshIndicator组件实现下拉刷新
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List _list = [];
_getData() async {
String apiUri =
"https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1";
var response = await Dio().get(apiUri);
var result = json.decode(response.data);
setState(() {
_list = result["result"];
});
}
@override
void initState() {
super.initState();
_getData();
}
@override
Widget build(BuildContext context) {
return _list.isNotEmpty
? RefreshIndicator(
onRefresh: () async {
print('下拉刷新');
await _getData();
},
child: ListView(
children: _list.map((e) {
return ListTile(
title: Text(e["title"]),
);
}).toList(),
),
)
: const Center(child: CircularProgressIndicator());
}
}
Flutter 上拉分页加载更多
上拉分页加载更多主要通过ListTile监听 ScrollController 实现
_scrollController.position.pixels 滚动的距离
_scrollController.position.maxScrollExtent 总距离
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
ScrollController _scrollController = ScrollController(); //listview的控制器
List _list = [];
int _page=1;
bool _flag = true; // 解决重复请求的问题
bool _hasMore = true; // 是否有更多数据的标志
_getData() async {
if(_flag && _hasMore){
_flag = false;
String apiUri =
"https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=$_page";
print(apiUri);
var response = await Dio().get(apiUri);
var result = json.decode(response.data);
if(result["result"].length < 20){
setState(() {
_hasMore = false;
});
}
setState(() {
_list.addAll(result["result"]);
_page++;
_flag = true;
});
}
}
@override
void initState() {
super.initState();
_getData();
// 监听滚动事件
_scrollController.addListener(() {
// 判断是否滚动到底部
if (_scrollController.position.pixels > _scrollController.position.maxScrollExtent-20) {
print('滑动到了底部');
_getData();
}
});
}
@override
Widget build(BuildContext context) {
return _list.isNotEmpty
? RefreshIndicator(
onRefresh: () async {
print('下拉刷新');
await _getData();
},
child: ListView.builder(
itemBuilder: (context, index) {
if (index == _list.length - 1) {
return Column(
children: [
ListTile(
title: Text(_list[index]["title"]),
),
_getMoreWidget(),
],
);
} else {
return Column(
children: [
ListTile(
title: Text(_list[index]["title"]),
),
],
);
}
},
itemCount: _list.length,
controller: _scrollController,
),
)
: _getMoreWidget();
}
// 自定义加载更多的组件
Widget _getMoreWidget() {
if (_hasMore) {
return Center(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Text('加载中...',style: TextStyle(fontSize: 16.0),),
CircularProgressIndicator(
strokeWidth: 1.0,
)
],
),
),
);
} else {
return const Center(
child: Text(
'没有更多数据了',
style: TextStyle(fontSize: 16.0),
),
);
}
}
}
Flutter实现一个简单的新闻系统
涉及的api接口
新闻列表: https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1
新闻详情:https://www.phonegap100.com/appapi.php?a=getPortalArticle&aid=20
flutter_html 解析html
flutter_html官方文档:https://pub.flutter-io.cn/packages/flutter_html
flutter_html示例demo: https://github.com/Sub6Resources/flutter_html/tree/master/example
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:flutter_html/flutter_html.dart';
class NewsContentPage extends StatefulWidget {
final Map arguments;
const NewsContentPage({super.key, required this.arguments});
@override
State<NewsContentPage> createState() => _NewsContentPageState();
}
class _NewsContentPageState extends State<NewsContentPage> {
List _list = [];
_getData() async {
String apiUri =
"https://www.phonegap100.com/appapi.php?a=getPortalArticle&aid=${widget.arguments['aid']}";
print(apiUri);
var response = await Dio().get(apiUri);
var result = json.decode(response.data);
setState(() {
_list = result['result'];
});
print(_list);
}
@override
void initState() {
super.initState();
print(widget.arguments);
_getData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('新闻详情页'),
),
body: _list.isNotEmpty ? ListView(
children: [
Text(_list[0]['title']),
Padding(
padding: const EdgeInsets.all(10),
child: Html(data: _list[0]['content']),
)
],
) : const Center(
child: CircularProgressIndicator(),
),
);
}
}
flutter_inappwebview 插件的使用
插件地址:https://pub.dev/packages/flutter_inappwebview
Example地址:https://github.com/pichillilorenzo/flutter_inappwebview/tree/master/example/lib