Flutter開發(fā) 項(xiàng)目實(shí)戰(zhàn)02

接著上篇

這篇最主要的是:

  1. GridView (flutter的橫向列表,相對(duì)于iOS的UICollectionView)

  2. httpClient (flutter的網(wǎng)絡(luò)請(qǐng)求,暫時(shí)會(huì)簡(jiǎn)單的數(shù)據(jù)處理,關(guān)于數(shù)據(jù)模型化還沒未到更快捷的方法,需要硬敲出來,沒有類似iOS中的YYModel一樣,直接一套)

3. 頁面的跳轉(zhuǎn)并傳參(上下級(jí)頁面通常需要傳遞參數(shù),類似詳情頁,可以減少網(wǎng)絡(luò)請(qǐng)求的次數(shù))

  1. flutter_refresh(flutter的一個(gè)上拉刷新下拉加載的插件,調(diào)用很簡(jiǎn)單,關(guān)于自定義刷新動(dòng)畫還需要更多的去了解,順便介紹關(guān)于根據(jù)條件來動(dòng)態(tài)布局)

1. Flutter的橫向列表GridView

flutter中橫向列表類似iOS中的UICollectionView的是GridView,開發(fā)前我沒有了解到這個(gè)控件,對(duì)于行數(shù)不多的,我直接使用listview自定義item硬寫,當(dāng)然復(fù)制代碼也是很快的,但是當(dāng)然需要更可塑性的布局方式。看下面這張圖我的頁面中的示例。

我的頁面
image

這個(gè)頁面總體是個(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屬性是用來設(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';

頁面一進(jìn)去的話在這里調(diào)用


void initState() {

super.initState();

_httpClient(PAGE);

}

其中setState這個(gè)方法刷新dataSource可以刷新頁面,flutter會(huì)檢測(cè)哪里用到了dataSource就會(huì)刷新那里的頁面,關(guān)于數(shù)據(jù)的是數(shù)組直接[index] 是map里取值就直接["key"],當(dāng)然你可以封裝一個(gè)數(shù)組里面包含返回值的所有key,這樣使用的時(shí)候就可以直接dataSource.key.key了,但是我這里沒有,因?yàn)榫蘼闊?。等找到高效的方法后再去修改吧?/p>

3. Flutter頁面的跳轉(zhuǎn)并傳參

在開發(fā)中,很多情況下需要傳遞參數(shù)到下級(jí)頁面,比如詳情頁,外部請(qǐng)求了一次,詳情頁就沒有必要再請(qǐng)求一次,可以上級(jí)頁面?zhèn)鬟^來使用。跳轉(zhuǎn)頁面根據(jù)Flutter的文檔,routes的靈感來源于reactjs,routes可以翻譯為路由,可以看到這種routes的思路在目前的設(shè)計(jì)中彼此借鑒,routes的思路不僅在前端流行,比如在vue、reactjs、Angular中用到,而且在后端應(yīng)用中也非常成熟。

關(guān)于頁面跳轉(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, ),

),

接下來看看頁面之間如何傳參數(shù)


////這是二級(jí)頁面的接收的寫法

class JokeDetailPageextends StatefulWidget {

 JokeDetailPage ({var key,this.mapd}):super(key:key);//接收從上一個(gè)頁面?zhèn)鱽淼闹?
 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í)頁面跳轉(zhuǎn)的時(shí)候就可以有提示了


////跳轉(zhuǎn)段子詳情   其中index是點(diǎn)擊某個(gè)item傳過來的 

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來拉到本地來,這個(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)基本的刷新頁面了哦。

下拉刷新
上拉加載

這里圖片加載用了一個(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è)我找了好久的資料沒找到,可能找到的方向不對(duì),看到代碼后,原來如此,也很簡(jiǎn)單。就拿下面的一段代碼來做示列。


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來判斷,如果dataSource有值說明可以創(chuàng)建Listview刷新頁面顯示數(shù)據(jù)了,但是如果為空的話就返回一個(gè)居中的文本,顯示正在加載中。一個(gè)簡(jiǎn)單的三目運(yùn)算就可以完成根據(jù)數(shù)據(jù)來布局,這種用法貫穿了很多的布局。所以要Get哦。

最后附上Github上的Demo的地址:Demo傳送門

還有開放API的地址:開放API

還有學(xué)習(xí)網(wǎng)站:

Flutter中文網(wǎng)

Flutter社區(qū)中文資源

如有不正確的地方幫忙指出,謝謝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,034評(píng)論 25 709
  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明AI閱讀 16,203評(píng)論 3 119
  • JavaScript學(xué)習(xí)筆記-(函數(shù)) 函數(shù) 1.函數(shù)的定義和調(diào)用 1. (x)括號(hào)內(nèi)列出函數(shù)的參數(shù),多個(gè)參數(shù)以,...
    locoo閱讀 635評(píng)論 0 0
  • 第一步 看包裝 1.1書名:書都不會(huì)讀,你還想成功 副標(biāo)題:神奇讀書法,職場(chǎng)菜鳥變CEO 1.2作者:二志成 鄭會(huì)...
    烏云的小筆記閱讀 257評(píng)論 0 0

友情鏈接更多精彩內(nèi)容