zoukankan      html  css  js  c++  java
  • Flutter中打造多行列列表GridView组件的使用

    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(
                       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),
          ),
        );
      }
  • 相关阅读:
    上班中午
    有些确实牛擦的有点嚣张!!! (zz)
    Docker学习笔记(二)
    结对项目第二阶段小结
    软件工程结课总结
    案例分析作业
    结对编程总结
    Docker学习笔记(一)
    四则运算
    构建之法1~5章
  • 原文地址:https://www.cnblogs.com/zengfp/p/10026541.html
Copyright © 2011-2022 走看看