Flutter實戰之實現一個簡單的新聞閱讀器

Introduction

紙上談兵終覺淺,絕知此事要躬行。html

catsao(音:cat騷),我擼的第一個Flutter Application Demo,目前階段它主要仿造目前主流的新聞資訊類app佈局,實現了簡單的新聞瀏覽。我還要繼續豐富它,讓它愈來愈sao。git

Points

  • TabBar實現:
@override
 Widget build(BuildContext context) {
   final List<Text> tabTexts = <Text>[
     new Text(
         StringResources.TAB_TOP_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_SH_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_GN_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_GJ_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_YL_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_TY_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_JS_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_KJ_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_CJ_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     ),
     new Text(
         StringResources.TAB_SS_CN,
         style: new TextStyle(
             fontSize: 20.0
         )
     )
   ];
   final List<Tab> tabs = [];
   for (int i = 0 ; i < tabTexts.length ; i++) {
     tabs.add(
       new Tab(
         child: tabTexts[i],
       )
     );
   }

   return new DefaultTabController(
       length: tabs.length,
       child: new Scaffold(
         appBar: new AppBar(
           title: new Text(
               widget.title
           ),
           bottom: new TabBar(
             isScrollable: true,
             tabs: tabs,

           ),
         ),
         body: new TabBarView(
             children: tabTexts.map((Text tab) {
               return new Center(
                 child: new NewsPage(
                   tabName: tab.data,
                 )
               );
             }).toList()
         ),
         drawer: new DrawerPage(),
       )
   );
 }
複製代碼

主要經過DefaultTabController + TabBar + TabBarView三個Widget配合實現相似Android中ViewPager + Indicator的效果。github

build方法返回的最外層是一個DefaultTabController Widget,正如它的名字那樣,它是一個控制器,用來控制TabBar和TabBarView的聯動。要在界面上繪製一個TabBar和其對應的內容頁使用TabBar和TabBarView兩個Widget來實現的。api

經過配置Scaffold的appbar參數爲界面添加一個標題欄,再配置AppBar的bottom參數爲標題欄添加一個顯示在其底部的Widget,在這裏傳遞給bottom參數的是一個TabBar Widget,因此在標題欄下方會顯示一個TabBar。TabBar的每一個Tab默認是固定位置的,這裏配置其isScrollable參數爲true使其可滾動,tabs參數配置TabBar中的每一個Tab Widget。瀏覽器

經過配置Scaffold的body參數爲其添加主內容界面,這裏的內容界面須要配合TabBar的切換而切換,因此配置一個TabBarView Widget。最終經過外層的DefaultTabController使得TabBar和TabBarView聯動起來。緩存

關於實現相似效果的更多詳細信息可參閱DefaultTabControllerTabBarTabBarViewapp

  • Drawer實現:
return new DefaultTabController(
       length: tabs.length,
       child: new Scaffold(
         appBar: new AppBar(
           title: new Text(
               widget.title
           ),
           bottom: new TabBar(
             isScrollable: true,
             tabs: tabs,

           ),
         ),
         body: new TabBarView(
             children: tabTexts.map((Text tab) {
               return new Center(
                 child: new NewsPage(
                   tabName: tab.data,
                 )
               );
             }).toList()
         ),
         drawer: new DrawerPage(),
       )
   );
複製代碼

Drawer的實現也很簡單,Flutter都已經封裝好了,直接配置Scaffold的drawer參數來實現一個Drawer界面。ide

  • 數據緩存:

利用shared_preferences和sqflite插件分別實現SharePreference和DB的數據本地緩存,在項目的pubspec.yaml中配置依賴的插件:佈局

dependencies:

  ......
 sqflite: "^0.8.3"
 shared_preferences: "^0.4.0"
  ......
  
複製代碼

而後就能夠在使用的地方import相應的package來使用對應功能。flex

  • Column問題

使用Column時會遇到一個there are children with non-zero flex but the vertical constraints are unbounded的異常,大體意思是說Column內部有flex值不爲0的children,可是當前Column在垂直方向的高度約束是無限制的。 簡單解釋一下,Column的children默認flex值是0,能夠理解爲flex爲0的組件佔用的空間是靜態的。當一個組件的flex值不爲0時,意味着它會去佔用父容器佈局完其餘flex爲0的組件後剩下的空間,佔用多少跟flex的值有關。這有點相似Android中LinearLayout的weight。因此這個異常的意思實際上是說由於當前的Column的垂直方向的高度約束是沒有任何限制的,此時內部若是有flex非0的children的話它沒法肯定父容器的剩餘空間有多大。

當一個Column的children中有一個或多個Expanded或Flexible組件,而且這個Column嵌套在另外一個Column或ListView的內部,就會遇到這個問題。

解決的思路其實就是檢查爲何本身的Column此時在垂直方向的高度約束是無限制的,大部分狀況下多是因爲當前Column嵌套在另外一個Column或ListView等容器中致使的。

關於該問題的詳細描述能夠參閱官方文檔

Effect

因爲聚合數據只有獲取新聞列表的接口(也可能我沒找到單條新聞詳情的接口),因此目前點擊新聞的跳轉是直接用瀏覽器打開了其對應的url。另外聚合數據獲取新聞列表的接口貌似也沒有支持分頁參數...我還升級了聚合數據的高級會員,略坑。

Todo

  • 下拉刷新
  • 增長不一樣頻道Route
  • 圖片本地緩存

End

天氣接口:和風天氣。

新聞接口:聚合數據。

部分圖標:Iconfont-阿里巴巴矢量圖標庫。

源碼地址:Catsao

關於Flutter項目的編譯和運行能夠參考官方文檔

相關文章
相關標籤/搜索