接著上篇
這篇最主要的是:
GridView (flutter的橫向列表胃碾,相對(duì)于iOS的UICollectionView)
httpClient (flutter的網(wǎng)絡(luò)請(qǐng)求,暫時(shí)會(huì)簡(jiǎn)單的數(shù)據(jù)處理悠就,關(guān)于數(shù)據(jù)模型化還沒(méi)未到更快捷的方法,需要硬敲出來(lái),沒(méi)有類似iOS中的YYModel一樣,直接一套)
3. 頁(yè)面的跳轉(zhuǎn)并傳參(上下級(jí)頁(yè)面通常需要傳遞參數(shù)趟径,類似詳情頁(yè),可以減少網(wǎng)絡(luò)請(qǐng)求的次數(shù))
- flutter_refresh(flutter的一個(gè)上拉刷新下拉加載的插件癣防,調(diào)用很簡(jiǎn)單舵抹,關(guān)于自定義刷新動(dòng)畫(huà)還需要更多的去了解,順便介紹關(guān)于根據(jù)條件來(lái)動(dòng)態(tài)布局)
1. Flutter的橫向列表GridView
flutter中橫向列表類似iOS中的UICollectionView的是GridView劣砍,開(kāi)發(fā)前我沒(méi)有了解到這個(gè)控件,對(duì)于行數(shù)不多的扇救,我直接使用listview自定義item硬寫(xiě)刑枝,當(dāng)然復(fù)制代碼也是很快的,但是當(dāng)然需要更可塑性的布局方式迅腔∽俺看下面這張圖我的頁(yè)面中的示例。
這個(gè)頁(yè)面總體是個(gè)ListView沧烈,對(duì)應(yīng)的是每個(gè)item掠兄,其中紅框就是個(gè)GridView,以下是創(chuàng)建GridView的代碼
//GridView的創(chuàng)建代碼
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的個(gè)數(shù)
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;
}
以上就可以實(shí)現(xiàn)一個(gè)橫向的GridView蚂夕,我相信閱覽了代碼后也知道如何使用,其中childAspectRatio屬性是用來(lái)設(shè)置item寬高比的腋逆,如果不設(shè)置默認(rèn)寬高一樣婿牍。
2. Flutter的網(wǎng)絡(luò)請(qǐng)求
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();
}
//更新數(shù)據(jù)
setState(() {
if(page ==1) {
dataSource = newData;
}else {
for (int a =0; a
dataSource.add(newData[a]);
}
}
});
}else {
print("error");
}
}
還要包含兩個(gè)頭文件哦
import 'dart:io';
import 'dart:convert';
頁(yè)面一進(jìn)去的話在這里調(diào)用
void initState() {
super.initState();
_httpClient(PAGE);
}
其中setState這個(gè)方法刷新dataSource可以刷新頁(yè)面,flutter會(huì)檢測(cè)哪里用到了dataSource就會(huì)刷新那里的頁(yè)面惩歉,關(guān)于數(shù)據(jù)的是數(shù)組直接[index] 是map里取值就直接["key"]等脂,當(dāng)然你可以封裝一個(gè)數(shù)組里面包含返回值的所有key俏蛮,這樣使用的時(shí)候就可以直接dataSource.key.key了,但是我這里沒(méi)有上遥,因?yàn)榫蘼闊┎肌5日业礁咝У姆椒ê笤偃バ薷陌伞?/p>
3. Flutter頁(yè)面的跳轉(zhuǎn)并傳參
在開(kāi)發(fā)中,很多情況下需要傳遞參數(shù)到下級(jí)頁(yè)面粉楚,比如詳情頁(yè)辣恋,外部請(qǐng)求了一次,詳情頁(yè)就沒(méi)有必要再請(qǐng)求一次解幼,可以上級(jí)頁(yè)面?zhèn)鬟^(guò)來(lái)使用抑党。跳轉(zhuǎn)頁(yè)面根據(jù)Flutter的文檔,routes的靈感來(lái)源于reactjs撵摆,routes可以翻譯為路由底靠,可以看到這種routes的思路在目前的設(shè)計(jì)中彼此借鑒,routes的思路不僅在前端流行特铝,比如在vue暑中、reactjs、Angular中用到鲫剿,而且在后端應(yīng)用中也非常成熟鳄逾。
關(guān)于頁(yè)面跳轉(zhuǎn)的代碼
////跳轉(zhuǎn)段子詳情
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, ),
),
接下來(lái)看看頁(yè)面之間如何傳參數(shù)
////這是二級(jí)頁(yè)面的接收的寫(xiě)法
class JokeDetailPageextends StatefulWidget {
JokeDetailPage ({var key,this.mapd}):super(key:key);//接收從上一個(gè)頁(yè)面?zhèn)鱽?lái)的值
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();
}
}
我這里傳的是個(gè)var類型的數(shù)據(jù),也可以傳其他數(shù)據(jù)類型的灵莲。在上級(jí)頁(yè)面跳轉(zhuǎn)的時(shí)候就可以有提示了
////跳轉(zhuǎn)段子詳情 其中index是點(diǎn)擊某個(gè)item傳過(guò)來(lái)的
pushAnotherView(int index){
print(index);
Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context) {
var data =dataSource[index];
return new JokeDetailPage(mapd: data);////這里就可以傳遞參數(shù)了
}
)
);
}
4. flutter_refresh
一個(gè)上拉加載雕凹,下拉刷新的控件。這是個(gè)插件政冻,所以我們需要在pubspec.yaml文件中添加這個(gè)插件及版本號(hào)枚抵,然后運(yùn)行Packages get來(lái)拉到本地來(lái),這個(gè)插件的鏈接地址: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);
});
});
}
以上就可以實(shí)現(xiàn)基本的刷新頁(yè)面了哦汽摹。
這里圖片加載用了一個(gè)插件transparent_image,占位符淡入圖片苦锨。
child:new FadeInImage.memoryNetwork(
alignment: Alignment.centerLeft,
placeholder: kTransparentImage,
image:dataSource[index]["thumbnail"],
fit: BoxFit.cover,
)
還要介紹以下根據(jù)條件動(dòng)態(tài)布局逼泣,這個(gè)我找了好久的資料沒(méi)找到,可能找到的方向不對(duì)舟舒,看到代碼后拉庶,原來(lái)如此,也很簡(jiǎn)單魏蔗。就拿下面的一段代碼來(lái)做示列砍的。
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根據(jù)了dataSource來(lái)判斷,如果dataSource有值說(shuō)明可以創(chuàng)建Listview刷新頁(yè)面顯示數(shù)據(jù)了莺治,但是如果為空的話就返回一個(gè)居中的文本廓鞠,顯示正在加載中帚稠。一個(gè)簡(jiǎn)單的三目運(yùn)算就可以完成根據(jù)數(shù)據(jù)來(lái)布局,這種用法貫穿了很多的布局床佳。所以要Get哦滋早。
最后附上Github上的Demo的地址:Demo傳送門(mén)
還有開(kāi)放API的地址:開(kāi)放API
還有學(xué)習(xí)網(wǎng)站:
如有不正確的地方幫忙指出,謝謝砌们。