Flutter中打造多行列列表GridView元件的使用
阿新 • • 發佈:2018-11-27
GridView元件。一個可滾動的二維空間陣列。
在使用無限載入滾動列表的時候,最先使用的還是ListView元件。但若是要一行顯示2列或者更多列的滾動列表,GridView元件更為方便。如下
在向伺服器請求資料後,伺服器往往會返回一段json字串。而我們要想更加靈活的使用資料的話需要把json字串轉化成物件。由於flutter只提供了json to Map。而手寫反序列化在大型專案中極不穩定,很容易導致解析失敗。所有最好使用json_serializable 自動反序列化。
首先在pubspec.yaml檔案中dependencies新增json_annotation,dev_dependencies新增json_serializable
dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 json_annotation: ^2.0.0 cached_network_image: ^0.5.1 transparent_image: ^0.1.0 dio: ^1.0.9 video_player:^0.7.2 flutter_spinkit: ^2.1.0 dev_dependencies: build_runner: ^1.0.0 json_serializable: ^2.0.0 flutter_test: sdk: flutter
以json_serializable的方式建立model類
建立一個模型picmodel.dart
import 'package:json_annotation/json_annotation.dart'; part 'picmodel.g.dart'; @JsonSerializable() class PicModel { PicModel(this.createdAt,this.publishedAt,this.type,this.url); String createdAt; String publishedAt; String type; String url; factory PicModel.fromJson(Map<String,dynamic> json) => _$PicModelFromJson(json); }
此時這個picmodel.g.dart檔案是不存在的,必須執行程式碼生成器來為我們生成序列化模板。通過在我們的專案根目錄下執行flutter packages pub run build_runner build
,我們可以在需要時為我們的model生成json序列化程式碼。 這觸發了一次性構建,它通過我們的原始檔,挑選相關的併為它們生成必要的序列化程式碼。
然後建立find.dart檔案,搭建基礎構架。引入相關的庫
import 'package:flutter/material.dart'; import 'dart:io'; import 'dart:convert'; import 'package:flutter_yuan/models/picmodel.dart'; import 'package:cached_network_image/cached_network_image.dart'; class FindPage extends StatefulWidget{ FindPage({Key key}):super(key:key); @override createState() => new _FindPageState(); } class _FindPageState extends State<FindPage> { List<PicModel> picList = new List(); int page = 1; @override void initState() { super.initState(); _getPicList(); } @override Widget build(BuildContext context) { return new Scaffold( ); } }
我們需要通過_getPicList來非同步請求資料:
_getPicList() async{ String url = 'https://www.apiopen.top/meituApi?page=$page'; var httpClient = new HttpClient(); try { var req = await httpClient.getUrl(Uri.parse(url)); var res = await req.close(); // print(res); if(res.statusCode == HttpStatus.OK) { var jsonString = await res.transform(utf8.decoder).join();//將結果轉換成字串拼接 // print(jsonString); Map data = jsonDecode(jsonString);//格式化成Map物件 print(data); List pics = data['data']; List<PicModel> items = new List(); for (var value in pics) { items.add(new PicModel.fromJson(value)); }; setState(() { this.picList.addAll(items); this.page ++; }); } } catch (e) { } }
然後構建Widget:
Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text('美圖'), centerTitle: true, ), body: new GridView.builder( padding: const EdgeInsets.all(10.0), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, mainAxisSpacing: 10.0, crossAxisSpacing: 10.0, ), itemCount: picList.length, itemBuilder: (BuildContext context, int index) { if(index == picList.length - 1 ){ _getPicList(); } return buildItem(picList[index]); }, ), ); }
使用GridView.builder元件來構建列表,通過gridDelegate屬性來對列表樣式進行豐富。crossAxisCount屬性可以設定每行的列數,打造你的瀑布流佈局。
buidItem方法對圖片的樣式佈局。
buildItem(item) { return new GestureDetector( onTap: () { Navigator.push( context, new MaterialPageRoute( builder: (context) => new Scaffold( appBar: new AppBar( title: new Text('圖片詳情'), ), body: new Center( child: new Container( width: 300.0, child: new CachedNetworkImage( imageUrl: item.url, fit: BoxFit.fitWidth, ), ) ), ) ) ); }, child: new CachedNetworkImage( errorWidget: new Icon(Icons.error), imageUrl: item.url, fadeInDuration: new Duration(seconds: 3), fadeOutDuration: new Duration(seconds: 1), ), ); }