效果图:
点击这三个新闻列表的内容,即可进入新闻详情
学习之前需要导入Dio库,具体用法与导入连接请查看我的博客
Flutter进阶第2篇:Dio库实现网络请求以及动态渲染数据
还需要导入解析HTML代码的第三方库:
flutter_html
新闻列表代码:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:dio/dio.dart';
class NewsPage extends StatefulWidget {
NewsPage({Key key}) : super(key: key);
_NewsPageState createState() => _NewsPageState();
}
class _NewsPageState extends State<NewsPage> {
List _list = [];
int _page = 1;
bool hasMore = true; //判断有没有数据
ScrollController _scrollController = new ScrollController();
@override
void initState() {
super.initState();
this._getData();
//监听滚动条事件
_scrollController.addListener(() {
print(_scrollController.position.pixels); //获取滚动条下拉的距离
print(_scrollController.position.maxScrollExtent); //获取整个页面的高度
if (_scrollController.position.pixels >
_scrollController.position.maxScrollExtent - 40) {
this._getData();
}
});
}
void _getData() async {
if (this.hasMore) {
var apiUrl =
"http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=${_page}";
var response = await Dio().get(apiUrl);
var res = json.decode(response.data)["result"];
setState(() {
this._list.addAll(res); //拼接
this._page++;
});
//判断是否是最后一页
if (res.length < 20) {
setState(() {
this.hasMore = false;
});
}
}
}
//下拉刷新
Future<void> _onRefresh() async {
await Future.delayed(Duration(milliseconds: 2000), () {
print('请求数据完成');
_getData();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("新闻列表"),
),
body: this._list.length > 0
? RefreshIndicator(
onRefresh: _onRefresh,
child: ListView.builder(
controller: _scrollController,
itemCount: this._list.length, //20
itemBuilder: (context, index) {//19
if (index == this._list.length-1) { //列表渲染到最后一条的时候加一个圈圈
//拉到底
return Column(
children: <Widget>[
ListTile(
title: Text("${this._list[index]["title"]}",
maxLines: 1),
onTap: (){
Navigator.pushNamed(context, '/newscontent',arguments:{
"aid":this._list[index]["aid"]
});
},
),
Divider(),
_getMoreWidget()
],
);
} else {
return Column(
children: <Widget>[
ListTile(
title: Text("${this._list[index]["title"]}",
maxLines: 1),
onTap: (){
Navigator.pushNamed(context, '/newscontent',arguments:{
"aid":this._list[index]["aid"]
});
},
),
Divider()
],
);
}
},
))
: _getMoreWidget(),
);
}
//加载中的圈圈
Widget _getMoreWidget() {
if(hasMore){
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,
)
],
),
),
);
}else{
return Center(
child: Text("--我是有底线的--"),
);
}
}
}
新闻详情
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter_html/flutter_html.dart';
class NewsContent extends StatefulWidget {
Map arguments;
NewsContent({Key key,this.arguments}) : super(key: key);
_NewsContentState createState() => _NewsContentState(this.arguments);
}
class _NewsContentState extends State<NewsContent> {
Map arguments;
List _list=[];
_NewsContentState(this.arguments);
@override
void initState() {
// TODO: implement initState
super.initState();
print(this.arguments);
this._getData();
}
_getData() async{
var apiUrl="http://www.phonegap100.com/appapi.php?a=getPortalArticle&aid=${this.arguments["aid"]}";
var response=await Dio().get(apiUrl);
setState(() {
this._list=json.decode(response.data)["result"];
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("新闻详情")
),
body:ListView(
children: <Widget>[
// Text("${this._list.length>0?this._list[0]["title"]:''}"),
// Text("${this._list.length>0?this._list[0]["content"]:''}")
Html(
data: """
${this._list.length>0?this._list[0]["content"]:''}
""",
//Optional parameters:
padding: EdgeInsets.all(8.0),
backgroundColor: Colors.white70,
defaultTextStyle: TextStyle(fontFamily: 'serif'),
linkStyle: const TextStyle(
color: Colors.redAccent,
),
onLinkTap: (url) {
// open url in a webview
}
)
],
)
);
}
}
记得配置路由时,要传值: