紙上談兵終覺淺,絕知此事要躬行。html
catsao(音:cat騷),我擼的第一個Flutter Application Demo,目前階段它主要仿造目前主流的新聞資訊類app佈局,實現了簡單的新聞瀏覽。我還要繼續豐富它,讓它愈來愈sao。git
@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聯動起來。緩存
關於實現相似效果的更多詳細信息可參閱DefaultTabController,TabBar,TabBarView。app
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時會遇到一個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等容器中致使的。
關於該問題的詳細描述能夠參閱官方文檔。
因爲聚合數據只有獲取新聞列表的接口(也可能我沒找到單條新聞詳情的接口),因此目前點擊新聞的跳轉是直接用瀏覽器打開了其對應的url。另外聚合數據獲取新聞列表的接口貌似也沒有支持分頁參數...我還升級了聚合數據的高級會員,略坑。
天氣接口:和風天氣。
新聞接口:聚合數據。
部分圖標:Iconfont-阿里巴巴矢量圖標庫。
源碼地址:Catsao
關於Flutter項目的編譯和運行能夠參考官方文檔。