移动端UI展示最常见的展示形式莫过于列表,Android中使用ListView/Recyclerview,iOS也有UIListView,都可以实现列表展示。Flutter作为兼容Android和iOS的移动UI框架,自然也有实现此功能的组件,即ListView。
本文数据采用爬虫爬取华尔街见闻全球资讯,然后采用GraphQL接口请求数据。显示效果如下
使用如下代码创建一个ListView
其中listData 为列表加载的数据,因先初始化下 List listData = [];
ListView getListView() => new ListView.builder(
itemCount: (listData== null) ? 0 : listData.length,
itemBuilder: (BuildContext context, int position) {
return getItem(position);
});
上面的getItem方法即为列表item的布局,使用Column与Row实现垂直和水平布局,核心代码如下:
new Padding(
padding: new EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: new Column(
children: [
new Row(
crossAxisAlignment: CrossAxisAlignment.start, //纵向对齐方式:起始边对齐
mainAxisSize: MainAxisSize.max,
children: [
new Expanded(
child: Container(
height: 95.0,
child: getImage(data.articleThumbnail),//封面
alignment: FractionalOffset.center,
),
flex: 1,
),
new Expanded(
child: Container(
height: 95.0,
margin: new EdgeInsets.fromLTRB(5.0, 0.0, 0.0, 0.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new Container(
child: new Text(
articleTitle,//标题
style: new TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w700),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
alignment: FractionalOffset.topLeft,
),
new Container(
child: new Text("${data.articleBrief}",//概要
style: new TextStyle(fontSize: 16.0),
maxLines: 2,
overflow: TextOverflow.ellipsis),
alignment: Alignment.topLeft,
),
new Expanded(
child: new Container(
margin:
new EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 0.0),
child: new Stack(
children: [
new Container(
child: new Text("${data.articleAuthor}",
style: new TextStyle(fontSize: 10.0)),//作者
alignment: FractionalOffset.bottomLeft,
),
new Container(
child: new Text(time_str,
style: new TextStyle(fontSize: 10.0)),//时间
alignment: FractionalOffset.bottomRight,
),
],
),
),
)
],
),
),
flex: 3,
),
],
),
new Divider(), //分割线
],
),
)
/**
* 列表中图片加载
*/
getImage(String img_url) {
return new CachedNetworkImage(
imageUrl: img_url,
errorWidget: new Icon(Icons.error),
fit: BoxFit.cover,
height: 85.0,
width: 100.0,
);
}
上述代码对应显示效果如下:
代码中CachedNetworkImage为网络图片缓存组件cached_network_image加载。
网络请求使用的是开源的Dio,也可以直接使用http发送请求,
Dio dio = new Dio();
Response response = await dio.get(url);
var jsonString = response.data;
json_serializable这个可以对json做很好的解析,类似于安卓的Gson,具体使用可以参考这篇文章,博主也是按文章进行操作的。
try {
var news = new news_enity.fromJson(jsonString);
var code = news.code;
if (code == 0) {
Result result = news.result;
datas = result.data;
}
} catch (e) {
print("异常==》" + e.toString());
}
使用 setState,将请求获得的数据datas传递给ListView的数据源listData
setState(() {
listData= datas;
});
但列表显示肯定是要等到下网络请求到时间后才能显示的,所以有段时间我们需要用精度条转圈来显示等待,没有数据时,加载loading进度条,有数据后立马显示列表
getBody() {
if (listData.isEmpty) {
return getProgressDialog();
} else {
return new Container(
padding: new EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 10.0),
child: getListView(),
);
}
}
getProgressDialog() {
// // CircularProgressIndicator是一个圆形的Loading进度条
return new Center(child: new CircularProgressIndicator());
}
项目源代码地址,此项目为持续开发项目,欢迎Star和Fork