目錄
- 頂部TabBar + TabBarView
- 瀑布流照片墻
- 圖片加載策略
頂部TabBar + TabBarView

image.png
TabBarView和TabBar都有一個tabController的參數(shù)
TabBarView和Tab是就由TabController來控制同步的,點擊了某個tab后,要同步的顯示對應(yīng)的TabBarView。TabController的創(chuàng)建有兩種形式,一種是使用系統(tǒng)的DefaultTabController,這種方式很簡單,只要在Scaffold上面再套一層DefaultTabController就可以了。這種方式下,TabBarView會自動去查找這個tabController,如果找不到就會報錯。
initState()中兩次初始化controller
@override
void initState() {
_controller = TabController(length: tabs.length, vsync: this); // 初始化空的controller,防止Null引用
TravelTabDao.fetch().then((TravelTabModel model) {
_controller = TabController(length: model.tabs.length, vsync: this); // 獲得數(shù)據(jù)再次初始化數(shù)據(jù)。
setState(() {
tabs = model.tabs;
travelTabModel = model;
});
}).catchError((e) {
print(e);
});
super.initState();
}
indicator指示器:
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
color: Color(0xff2fcfbb),
width: 3,
),
insets: EdgeInsets.fromLTRB(0, 0, 0, 10),// 控制指示器的位置。
),
Flexible(): 解決TabBarView布局約束寬度與高度丟失的問題。
Flexible組件可以使Row、Column、Flex等子組件在主軸方向有填充可用空間的能力(例如,Row在水平方向,Column在垂直方向),但是它與Expanded組件不同,它不強制子組件填充可用空間
瀑布流照片墻
POST請求照片墻圖片。
- 動態(tài)改變POST請求的參數(shù)。
static Future<TravelItemModel> fetch(String url, String groupChannelCode, int pageIndex, int pageSize,) async {
Map paramsMap = Params['pagePara'];
paramsMap['pageIndex'] = pageIndex;
paramsMap['pageSize'] = pageSize;
Params['groupChannelCode'] = groupChannelCode;
var body = jsonEncode(Params);//
var response = await http.post(url, body: body);
if (response.statusCode == 200) {
Utf8Decoder utf8decoder = Utf8Decoder(); // fix 中文亂碼
var result = json.decode(utf8decoder.convert(response.bodyBytes));
return TravelItemModel.fromJson(result);
} else {
throw Exception('Failed to load travel_page.json');
}
}
- 當我們使用TabBar,TabBarView是我們就會發(fā)現(xiàn),切換tab,initState又會被調(diào)用一次。
怎么為了讓tab一直保存在內(nèi)存中,不被銷毀?
添加AutomaticKeepAliveClientMixin,并設(shè)置為true,這樣就能一直保持當前不被initState了。
class _TravelTabPageState extends State<TravelTabPage> with AutomaticKeepAliveClientMixin
@override
bool get wantKeepAlive => true;
-
crossAxisCount:橫軸子元素的數(shù)量。此屬性值確定后子元素在橫軸的長度就確定了,即ViewPort橫軸長度/crossAxisCount。
staggeredTileBuilder:該屬性可以控制當前 Cell 占用的空間大小, 用來實現(xiàn)瀑布的感覺
Card:Card接受單個widget,但該widget可以是Row,Column或其他包含子級列表的widget。Card內(nèi)容不能滾動
CachedImage:緩存的網(wǎng)絡(luò)映像使用flutter_cache_manager存儲和檢索文件。
默認情況下,緩存的文件存儲在應(yīng)用程序的臨時目錄中。這意味著操作系統(tǒng)可以隨時刪除文件。
有關(guān)文件的信息使用sqflite存儲在數(shù)據(jù)庫中。數(shù)據(jù)庫的文件名是cacheManager的鍵,這就是為什么它必須是惟一的。
此緩存信息包含到文件有效時為止的結(jié)束日期,以及與http緩存控件一起使用的eTag。
return Scaffold(
body: LoadingContainer(
// Loading
isLoading: _loading,
child: RefreshIndicator(
// 下拉刷新
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: StaggeredGridView.countBuilder(
controller: _scrollController, // 配置下拉加載更多
crossAxisCount: 2, // 橫軸子元素的數(shù)量。此屬性值確定后子元素在橫軸的長度就確定了,即ViewPort橫軸長度/crossAxisCount。
itemCount: travelItems?.length ?? 0,
itemBuilder: (BuildContext context, int index) =>
_TravelItem(index: index, item: travelItems[index]),
// // 該屬性可以控制當前 Cell 占用的空間大小, 用來實現(xiàn)瀑布的感覺
staggeredTileBuilder: (int index) =>
new StaggeredTile.fit(1),
)
),
onRefresh: _handleRefresh
)
)
);