接着上篇
这篇最主要的是:
GridView (flutter的横向列表,相对于iOS的UICollectionView)
httpClient (flutter的网络请求,暂时会简单的数据处理,关于数据模型化还没未到更快捷的方法,需要硬敲出来,没有类似iOS中的YYModel一样,直接一套)
3. 页面的跳转并传参(上下级页面通常需要传递参数,类似详情页,可以减少网络请求的次数)
- flutter_refresh(flutter的一个上拉刷新下拉加载的插件,调用很简单,关于自定义刷新动画还需要更多的去了解,顺便介绍关于根据条件来动态布局)
1. Flutter的横向列表GridView
flutter中横向列表类似iOS中的UICollectionView的是GridView,开发前我没有了解到这个控件,对于行数不多的,我直接使用listview自定义item硬写,当然复制代码也是很快的,但是当然需要更可塑性的布局方式。看下面这张图我的页面中的示例。
这个页面总体是个ListView,对应的是每个item,其中红框就是个GridView,以下是创建GridView的代码
//GridView的创建代码
doubleItemWidth= ScreenWidth /4.0;
doubleItemHeight=70.0;
var cellItemMiddleInfo =new GestureDetector(
onTap: ()=>{},
child:new Container(
width: ScreenWidth,
child:new Column(
children: [
new Container(
width: ScreenWidth,
height: SmallMiddleHeight *2.0,
color: Colors.white,
child:new GridView.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
mainAxisSpacing:0.0,//竖向间距
// crossAxisCount: 4,//横向Item的个数
maxCrossAxisExtent: ScreenWidth/4.0,
crossAxisSpacing:0.0,//横向间距
childAspectRatio:(ItemWidth/ItemHeight)
),
primary:false,
itemCount: List2.length,
itemBuilder: MyItemImageText,
)
),
new Divider(height:1.0,),
new Container(
width: ScreenWidth,
height:15.0,
),
new Divider(height:1.0,),
],
)
),
);
//GridView也需要子item,这是子item的代码
////////中间部分的操作栏 私密文章 我的收藏 我的喜欢 等
WidgetMyItemImageText(BuildContext context, int index) {
doubleScreenWidth= MediaQuery.of(context).size.width;
doubleItemWidth= ScreenWidth /4.0;
doubleItemHeight=70.0;
var Item=new GestureDetector(
onTap: (){},
child:new Container(
width: ItemWidth,
height: ItemHeight,
// color: Colors.red,
child:new Column(
children: [
///顶部 图片
new Container(
alignment: Alignment.center,
margin:new EdgeInsets.only(left:10.0, right:10.0, top:14.0),
height:18.0,
child:new Container(
alignment: Alignment.center,
height:18.0,
width:18.0,
child:new Image.asset(List2[index].itemImageSrc),
)
),
//底部的text
new Container(
alignment: Alignment.center,
margin:new EdgeInsets.only(left:10.0, right:10.0, top:7.0),
height:15.0,
child:new Text(List2[index].downText, style:new TextStyle(fontSize:12.0, color:new Color.fromARGB(255,123,123,123)), softWrap:false, overflow: TextOverflow.ellipsis),
),
],
),
),
);
return Item;
}
以上就可以实现一个横向的GridView,我相信阅览了代码后也知道如何使用,其中childAspectRatio属性是用来设置item宽高比的,如果不设置默认宽高一样。
2. Flutter的网络请求
ListdataSource;
void _httpClient(var page)async {
var responseBody;
var httpClient =new HttpClient();
var request =await httpClient.getUrl(
Uri.parse("https://www.apiopen.top/satinGodApi?type=1&page=${page}"));
var response =await request.close();
print(page);
if (response.statusCode ==200) {
responseBody =await response.transform(utf8.decoder).join();
ListnewData = jsonDecode(responseBody)["data"];
if(page ==1 &&dataSource !=null) {
dataSource.clear();
}
//更新数据
setState(() {
if(page ==1) {
dataSource = newData;
}else {
for (int a =0; a
dataSource.add(newData[a]);
}
}
});
}else {
print("error");
}
}
还要包含两个头文件哦
import 'dart:io';
import 'dart:convert';
页面一进去的话在这里调用
void initState() {
super.initState();
_httpClient(PAGE);
}
其中setState这个方法刷新dataSource可以刷新页面,flutter会检测哪里用到了dataSource就会刷新那里的页面,关于数据的是数组直接[index] 是map里取值就直接["key"],当然你可以封装一个数组里面包含返回值的所有key,这样使用的时候就可以直接dataSource.key.key了,但是我这里没有,因为巨麻烦。等找到高效的方法后再去修改吧。
3. Flutter页面的跳转并传参
在开发中,很多情况下需要传递参数到下级页面,比如详情页,外部请求了一次,详情页就没有必要再请求一次,可以上级页面传过来使用。跳转页面根据Flutter的文档,routes的灵感来源于reactjs,routes可以翻译为路由,可以看到这种routes的思路在目前的设计中彼此借鉴,routes的思路不仅在前端流行,比如在vue、reactjs、Angular中用到,而且在后端应用中也非常成熟。
关于页面跳转的代码
////跳转段子详情
pushAnotherView(int index){
print(index);
Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context) {
var data =dataSource[index];
return new JokeDetailPage(mapd: data);
}
)
);
}
////返回按钮
new FlatButton(
onPressed:(){
Navigator.pop(context);
},
color: Colors.white,
child:new Icon(Icons.keyboard_backspace,color: Colors.blue, ),
),
接下来看看页面之间如何传参数
////这是二级页面的接收的写法
class JokeDetailPageextends StatefulWidget {
JokeDetailPage ({var key,this.mapd}):super(key:key);//接收从上一个页面传来的值
var mapd;
@override
_JokeDetailPageState createState() =>new _JokeDetailPageState(mapd,mapd);
}
class _JokeDetailPageStateextends State {
_JokeDetailPageState(var key,this.mapd);
var mapd;
@override
void dispose() {
super.dispose();
}
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return new MaterialApp();
}
}
我这里传的是个var类型的数据,也可以传其他数据类型的。在上级页面跳转的时候就可以有提示了
////跳转段子详情 其中index是点击某个item传过来的
pushAnotherView(int index){
print(index);
Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context) {
var data =dataSource[index];
return new JokeDetailPage(mapd: data);////这里就可以传递参数了
}
)
);
}
4. flutter_refresh
一个上拉加载,下拉刷新的控件。这是个插件,所以我们需要在pubspec.yaml文件中添加这个插件及版本号,然后运行Packages get来拉到本地来,这个插件的链接地址:flutter_refresh。
使用方法
////chiild直接就是Refresh 添加头部尾部刷新方法和UI即可
return new Container(
child:dataSource!=null ?
new Refresh(
onFooterRefresh: onFooterRefresh,
onHeaderRefresh: onHeaderRefresh,
child:new ListView.builder(
itemCount:dataSource.length,
itemBuilder: buildCelljianyouquanItem1,
)
) :
new Container(child:new Text(tab.text)),
);
// 顶部刷新
Future onHeaderRefresh() {
return new Future.delayed(new Duration(seconds:2), () {
setState(() {
PAGE =1;
_httpClient(PAGE);
});
});
}
// 底部刷新
Future onFooterRefresh()async {
return new Future.delayed(new Duration(seconds:2), () {
setState(() {
PAGE +=1;
_httpClient(PAGE);
});
});
}
以上就可以实现基本的刷新页面了哦。
这里图片加载用了一个插件transparent_image,占位符淡入图片。
child:new FadeInImage.memoryNetwork(
alignment: Alignment.centerLeft,
placeholder: kTransparentImage,
image:dataSource[index]["thumbnail"],
fit: BoxFit.cover,
)
还要介绍以下根据条件动态布局,这个我找了好久的资料没找到,可能找到的方向不对,看到代码后,原来如此,也很简单。就拿下面的一段代码来做示列。
return new Container(
child:dataSource!=null ?
new Refresh(
onFooterRefresh: onFooterRefresh,
onHeaderRefresh: onHeaderRefresh,
child:new ListView.builder(
itemCount:dataSource.length,
itemBuilder: buildCelljianyouquanItem1,
)
):new Container(child:new Text(tab.text)),
);
这里我返回的Container根据了dataSource来判断,如果dataSource有值说明可以创建Listview刷新页面显示数据了,但是如果为空的话就返回一个居中的文本,显示正在加载中。一个简单的三目运算就可以完成根据数据来布局,这种用法贯穿了很多的布局。所以要Get哦。
最后附上Github上的Demo的地址:Demo传送门
还有开放API的地址:开放API
还有学习网站:
Flutter中文网
Flutter社区中文资源
如有不正确的地方帮忙指出,谢谢。