Flutter-常见的Cell布局设计03

2 阅读3分钟

要求:接入Dio框架,简单做下网络请求

main.dart 代码如下:

import 'dart:convert';
import 'dart:convert';
import 'dart:ffi';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:listdemo/model.dart';



void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  Dio dio = Dio();
  Model model =  Model();
  ///在Dart语言中,late关键字用于标记延迟初始化的非空变量。而没有使用late关键字的final变量将在声明时立即被赋值。
  // late final int totalCount;
  // final int totalCount = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: Container(
        child: CreateListView(),
        color: Colors.white,
      ),
    );
  }

  ///创建列表
  Widget CreateListView() {
    int? itemCount = model.data?.items?.length ?? 0;
    ///如果想要列表都有间隙 得使用ListView.separated,而不是 ListView.build
    return ListView.separated(
        separatorBuilder: (BuildContext context, int index) {
          return SizedBox(
            height: 12,
          );
        },
        itemCount: itemCount,

        ///列表项的数量
        itemBuilder: (BuildContext context, int index) {
          ///构建每个列表项的小部件
          return itemCount == 0 ? Container() : CreateCell(itemsModel: model.data!.items![index])  ;
        });
  }

  ///创建具体的Cell
  Widget CreateCell({required Items itemsModel}) {
    ///如果高度不固定,使用LayoutBuideer包装起来
    return LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          ///让cell距离上下左右都有间距,最外层得用Padding包装起来,才有效,不能在Container操作
          return Padding(
            padding: EdgeInsets.all(12),
            child: Container(
              // height: 44,
                decoration: BoxDecoration(
                    color: Colors.limeAccent,
                    borderRadius: BorderRadius.circular(10),

                    ///设置圆角半径为10
                    border: Border.all(color: Colors.amber, width: 2)),

                ///设置边框样式
                child: CreateBigCell(itemsModel: itemsModel)),
          );
        });
  }

  ///开始布局cell
  Widget CreateBigCell({required Items itemsModel}) {
    return  Column(
      children: [
        Row(
          children: [
            ///Image用于显示图像,可以加载本地资源图像或从网络加载图像。
            ///Icon用于显示矢量图标,使用预定义的字体图标集。
            Expanded(
                child: Row(
                  children: [
                    Text(
                      itemsModel.newsTime ?? "",
                      style: TextStyle(color: Colors.orange, fontSize: 16),
                    ),
                    Icon(Icons.g_translate)
                  ],
                )),

            ///使用Flexible,如果文字过长,自动换行
            Flexible(
              child: Text(
                itemsModel.title ?? "",
                style: TextStyle(color: Colors.orange, fontSize: 16),
              ),
            ),
            Icon(Icons.ac_unit),
          ],
        ),
        ///使用Divider 处理分割线
        Padding(
          padding: EdgeInsets.only(left: 12, right: 12),
          child: Divider(
            height: 3,
            color: Colors.deepOrange,
          ),
        ),
        Row(
          children: [
            Expanded(
              child:Padding(padding: EdgeInsets.only(left: 12),child: Column(
                children: [
                  Text(
                    itemsModel.id ??
                    "",
                    style: TextStyle(color: Colors.grey, fontSize: 13),
                  ),
                  Text(
                    itemsModel.viewCount.toString() ?? "0",
                    style: TextStyle(color: Colors.grey, fontSize: 13),
                  )
                ],
                /// 设置交叉轴上子部件对齐到起始位置,不然就居中了
                crossAxisAlignment: CrossAxisAlignment.start,
              )),),
            Column(
              children: [
                Text(
                  itemsModel.hotComment ?? "没有评论",
                  style: TextStyle(color: Colors.grey, fontSize: 13),
                ),
                Text(
                  itemsModel.commentNum.toString() ?? "",
                  style: TextStyle(color: Colors.grey, fontSize: 13),
                )
              ],
            ),
            SizedBox(width: 12,),
          ],
        ),
        SizedBox(height: 12,)
      ],
    );
  }


  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getData();
  }



  ///网络请求
  void getData() async {
    try {
      Response response = await dio.get(
          "https://app.guancha.cn/news/yaowen-new.json?",
          queryParameters: {"pageNo": "1", "device": "ios", "v": "8.3.8"});
      Map<String, dynamic> map = response.data;
      // debugPrint("get请求返回(格式化后): $map");
      model = Model.fromJson(map);
      ///setState 不能删除,相当于刷新作用,删除后列表则没有效果,当然也可以将model赋值放在setState回调内部
      setState(() {
        // model = Model.fromJson(map);
      });

    } catch (error) {
      print("请求报错:$error");
    }
  }
}

model.dart 代码如下:

class Model {
  int? code;
  String? msg;
  Data? data;

  Model({this.code, this.msg, this.data});

  Model.fromJson(Map<String, dynamic> json) {
    code = json['code'];
    msg = json['msg'];
    data = json['data'] != null ? new Data.fromJson(json['data']) : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['code'] = this.code;
    data['msg'] = this.msg;
    if (this.data != null) {
      data['data'] = this.data!.toJson();
    }
    return data;
  }
}

class Data {
  List<Items>? items;

  Data({this.items});

  Data.fromJson(Map<String, dynamic> json) {
    if (json['items'] != null) {
      items = <Items>[];
      json['items'].forEach((v) {
        items!.add(new Items.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.items != null) {
      data['items'] = this.items!.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Items {
  String? id;
  String? title;
  String? pic;
  String? summary;
  int? showType;
  Special? special;
  String? newsTime;
  int? newsType;
  int? commentNum;
  Author? author;
  User? user;
  String? url;
  int? viewCount;
  String? viewCountText;
  bool? hot;
  String? hotComment;

  Items(
      {this.id,
        this.title,
        this.pic,
        this.summary,
        this.showType,
        this.special,
        this.newsTime,
        this.newsType,
        this.commentNum,
        this.author,
        this.user,
        this.url,
        this.viewCount,
        this.viewCountText,
        this.hot,
        this.hotComment});

  Items.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    title = json['title'];
    pic = json['pic'];
    summary = json['summary'];
    showType = json['show_type'];
    special =
    json['special'] != null ? new Special.fromJson(json['special']) : null;
    newsTime = json['news_time'];
    newsType = json['news_type'];
    commentNum = json['comment_num'];
    author =
    json['author'] != null ? new Author.fromJson(json['author']) : null;
    user = json['user'] != null ? new User.fromJson(json['user']) : null;
    url = json['url'];
    viewCount = json['view_count'];
    viewCountText = json['view_count_text'];
    hot = json['hot'];
    hotComment = json['hot_comment'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['title'] = this.title;
    data['pic'] = this.pic;
    data['summary'] = this.summary;
    data['show_type'] = this.showType;
    if (this.special != null) {
      data['special'] = this.special!.toJson();
    }
    data['news_time'] = this.newsTime;
    data['news_type'] = this.newsType;
    data['comment_num'] = this.commentNum;
    if (this.author != null) {
      data['author'] = this.author!.toJson();
    }
    if (this.user != null) {
      data['user'] = this.user!.toJson();
    }
    data['url'] = this.url;
    data['view_count'] = this.viewCount;
    data['view_count_text'] = this.viewCountText;
    data['hot'] = this.hot;
    data['hot_comment'] = this.hotComment;
    return data;
  }
}

class Special {
  String? id;
  String? name;

  Special({this.id, this.name});

  Special.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['name'] = this.name;
    return data;
  }
}

class Author {
  String? id;
  String? name;
  String? pic;
  String? description;
  bool? isMore;

  Author({this.id, this.name, this.pic, this.description, this.isMore});

  Author.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    pic = json['pic'];
    description = json['description'];
    isMore = json['is_more'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['name'] = this.name;
    data['pic'] = this.pic;
    data['description'] = this.description;
    data['is_more'] = this.isMore;
    return data;
  }
}

class User {
  String? id;
  String? nick;
  String? pic;
  String? levelIcon;

  User({this.id, this.nick, this.pic, this.levelIcon});

  User.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    nick = json['nick'];
    pic = json['pic'];
    levelIcon = json['level_icon'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['nick'] = this.nick;
    data['pic'] = this.pic;
    data['level_icon'] = this.levelIcon;
    return data;
  }
}

以上两份文件,拷贝到项目就可以正常运行