20.flutter-表格

///数据模型

///派车次数统计 2
class SendCarNumberList {
  List titleList = []; //派车次数统计
  List sendCarList = []; //派车次数统计
  int count1 = 0; //抽样
  int count2 = 0; //还样

  ///派车次数统计 2
  SendCarNumberList.fromMap2(Map map) {
    if (map.isEmpty) return;
    this.titleList = _getTitleList(map["data"]);
    this.sendCarList = _getSendCarList(map["data"]);
  }

  ///派车次数统计 2
  List _getTitleList(Map map) {
    List newList = List.from(map["titles"]);
    return newList;
  }

  ///派车次数统计 2
  List _getSendCarList(Map map) {
    List newList = [];
    //CUM
    SendCarNumberModel model1 = SendCarNumberModel.fromMap(map["CUM"]);
    newList.add(model1);

    //抽样-CUM
    SendCarNumberModel model2 = SendCarNumberModel.fromMap(map["抽样"]["CUM"]);
    newList.add(model2);
    //抽样
    List list2 = List.from(map["抽样"]["details"]);
    this.count1 = list2.length;
    list2.forEach((element) {
      if (element is Map) {
        newList.add(SendCarNumberModel.fromMap(element));
      }
    });

    //还样-CUM
    SendCarNumberModel model3 = SendCarNumberModel.fromMap(map["还样"]["CUM"]);
    newList.add(model3);
    //还样
    List list3 = List.from(map["还样"]["details"]);
    this.count2 = list3.length;
    list3.forEach((element) {
      if (element is Map) {
        newList.add(SendCarNumberModel.fromMap(element));
      }
    });
    return newList;
  }
}

///派车次数统计 2
class SendCarNumberModel {
  String a;
  String b;
  String c;
  String d;
  String e;
  String f;
  String g;
  String h;
  String i;
  String j;
  String k;

  SendCarNumberModel({this.a, this.b, this.c, this.d, this.e, this.f, this.g, this.h, this.i, this.j, this.k});

  SendCarNumberModel.fromMap(Map map) {
    this.a = map["a"] != null ? map["a"].toString() : "";
    this.b = map["b"] != null ? map["b"].toString() : "";
    this.c = map["c"] != null ? map["c"].toString() : "";
    this.d = map["d"] != null ? map["d"].toString() : "";
    this.e = map["e"] != null ? map["e"].toString() : "";
    this.f = map["f"] != null ? map["f"].toString() : "";
    this.g = map["g"] != null ? map["g"].toString() : "";
    this.h = map["h"] != null ? map["h"].toString() : "";
    this.i = map["i"] != null ? map["i"].toString() : "";
    this.j = map["j"] != null ? map["j"].toString() : "";
    this.k = map["k"] != null ? map["k"].toString() : "";
  }

  List toList1() {
    List list = [];
    list.add(a);
    list.add(b);
    list.add(c);
    return list;
  }

  List toList2() {
    List list = [];

    list.add(d);
    list.add(e);
    list.add(f);
    list.add(g);
    list.add(h);
    list.add(i);
    list.add(j);
    list.add(k);
    return list;
  }
}

///派车次数统计 - 测试数据 2
var sendCarNumberTestData = {
  "error": 0, //0:正常;1:异常
  "message": "success", //正常:success;异常:fail具体异常描述
  "count": 0,
  "data": {
    "titles": ["2022", "2021", "Jul", "Aug", "WK32", "WK31", "08/12", "08/11"],
    "CUM": {
      "a": "CUM", //派车
      "b": "CUM", //始发
      "c": "CUM", //接收
      "d": "12956", //今年
      "e": "12565", //上一年
      "f": "126", //今月
      "g": "125", //上一月
      "h": "26", //今周
      "i": "30", //上一周
      "j": "10", //今天
      "k": "6", //上一天
    },
    "抽样": {
      "CUM": {
        "a": "抽样", //派车
        "b": "CUM", //始发
        "c": "CUM", //接收
        "d": "1295", //今年
        "e": "1255", //上一年
        "f": "12", //今月
        "g": "15", //上一月
        "h": "6", //今周
        "i": "3", //上一周
        "j": "1", //今天
        "k": "2", //上一天
      },
      "details": [
        {
          "a": "抽样", //派车
          "b": "C09V", //始发
          "c": "G11", //接收
          "d": "1256", //今年
          "e": "1265", //上一年
          "f": "16", //今月
          "g": "15", //上一月
          "h": "6", //今周
          "i": "3", //上一周
          "j": "1", //今天
          "k": "6", //上一天
        },
        {
          "a": "抽样", //派车
          "b": "C06V", //始发
          "c": "G112", //接收
          "d": "1256", //今年
          "e": "1265", //上一年
          "f": "16", //今月
          "g": "15", //上一月
          "h": "6", //今周
          "i": "3", //上一周
          "j": "1", //今天
          "k": "6", //上一天
        },
        {
          "a": "抽样", //派车
          "b": "C09V", //始发
          "c": "G11", //接收
          "d": "1256", //今年
          "e": "1265", //上一年
          "f": "16", //今月
          "g": "15", //上一月
          "h": "6", //今周
          "i": "3", //上一周
          "j": "1", //今天
          "k": "6", //上一天
        },
        {
          "a": "抽样", //派车
          "b": "C06V", //始发
          "c": "G112", //接收
          "d": "1256", //今年
          "e": "1265", //上一年
          "f": "16", //今月
          "g": "15", //上一月
          "h": "6", //今周
          "i": "3", //上一周
          "j": "1", //今天
          "k": "6", //上一天
        },
      ],
    },
    "还样": {
      "CUM": {
        "a": "还样", //派车
        "b": "CUM", //始发
        "c": "CUM", //接收
        "d": "1295", //今年
        "e": "1255", //上一年
        "f": "12", //今月
        "g": "15", //上一月
        "h": "6", //今周
        "i": "3", //上一周
        "j": "1", //今天
        "k": "2", //上一天
      },
      "details": [
        {
          "a": "还样", //派车
          "b": "C09V", //始发
          "c": "G11", //接收
          "d": "1256", //今年
          "e": "1265", //上一年
          "f": "16", //今月
          "g": "15", //上一月
          "h": "6", //今周
          "i": "3", //上一周
          "j": "1", //今天
          "k": "6", //上一天
        },
        {
          "a": "还样", //派车
          "b": "C06V", //始发
          "c": "G112", //接收
          "d": "1256", //今年
          "e": "1265", //上一年
          "f": "16", //今月
          "g": "15", //上一月
          "h": "6", //今周
          "i": "3", //上一周
          "j": "1", //今天
          "k": "6", //上一天
        },
        {
          "a": "还样", //派车
          "b": "C09V", //始发
          "c": "G11", //接收
          "d": "1256", //今年
          "e": "1265", //上一年
          "f": "16", //今月
          "g": "15", //上一月
          "h": "6", //今周
          "i": "3", //上一周
          "j": "1", //今天
          "k": "6", //上一天
        },
        {
          "a": "还样", //派车
          "b": "C06V", //始发
          "c": "G112", //接收
          "d": "1256", //今年
          "e": "1265", //上一年
          "f": "16", //今月
          "g": "15", //上一月
          "h": "6", //今周
          "i": "3", //上一周
          "j": "1", //今天
          "k": "6", //上一天
        },
      ],
    },
  }
};

界面实现

import 'package:flutter/material.dart';
import 'package:flutter_table/tools/custom_calendar_widget.dart';
import 'package:flutter_table/tools/layout.dart';
import 'package:flutter_table/tools/logs.dart';
import 'package:flutter_table/tools/name_color_widget.dart';
import 'package:flutter_table/tools/public_widget.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';

import 'data_statistics_chart_model.dart';

///派車次數統計(次)3
class SendCarNumberPage extends StatefulWidget {
  final String title; //派車次數統計

  const SendCarNumberPage({Key key, @required this.title}) : super(key: key);

  @override
  State createState() => _SendCarNumberPageState();
}

///Chaos20200829
class _SendCarNumberPageState extends State {
  //选择时间
  String _selectTime = "";

  //固定区域数据
  List _fixedAreas = ["派车", "始发", "接收"];
  //左边列表数据
  List _leftList = [];
  //右边标题数据
  List _rightTitles = ["2022", "2021", "Jul", "Aug", "WK32", "WK31", "08/12", "08/11"];
  //右边列表数据
  List _rightList = [];

  double _fixedAreaWidth = 150; //固定区域宽
  double _fixedAreaHeight = 40; //固定区域高
  double _itemWidth = 50; // item宽度
  double _itemHeight = 40; // item长度
  ScrollController _leftController; //左边数据-上下滚动控制器
  ScrollController _rightTitleController; //右边标题-左右滚动控制器
  ScrollController _rowController; //右边数据-左右滚动控制器
  ScrollController _columnController; //右边数据-上下滚动控制器
  LinkedScrollControllerGroup _verticalControllers; //垂直滚动同步
  LinkedScrollControllerGroup _horizontalControllers; //水平滚动同步

  int _count1 = 0; //抽样数据个数
  int _count2 = 0; //还样数据个数

  ///init
  @override
  void initState() {
    super.initState();
    //现在的时间
    _selectTime = DateTime.now().toString().split(".").first.split(" ").first;
    //初始化控制器配置
    _initController();
    //数据
    _getData();
  }

  ///dispose
  @override
  void dispose() {
    //销毁控制器
    _disposeController();
    super.dispose();
  }

  ///build
  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: w(50) + ((_rightList.length + 1) * w(40) + w(20) < w(385) ? (_rightList.length + 1) * w(40) + w(20) : w(385)),
      color: Colors.white,
      padding: EdgeInsets.symmetric(horizontal: w(16)),
      child: Column(
        children: [
          _getTopWidget(widget.title, "images/iqc_sampling_sys/icon-data434.png"),
          Expanded(child: _getForm()),
          Container(height: w(20), color: Colors.white),
        ],
      ),
    );
  }

  //界面..

  ///标题+时间选择 0
  _getTopWidget(String title, String imagePath) {
    return Container(
      width: double.infinity,
      height: w(50),
      alignment: Alignment.center,
      color: Colors.white,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          getTitle("$title(次)", Color(0xff000000), sp(18), fontWeight: FontWeight.bold),
          _getTextImage(imagePath, _selectTime),
        ],
      ),
    );
  }

  ///时间选择 0
  _getTextImage(String imagePath, String title) {
    return InkWell(
      onTap: () {
        logs("选择时间...");
        _showCalendar();
      },
      child: getTextImage(imagePath, title),
    );
  }

  ///弹窗-日历 0
  _showCalendar() {
    return showDialog(
        context: context,
        barrierColor: Color(0x66000000),
        builder: (context) {
          return Scaffold(
            backgroundColor: Colors.transparent,
            body: CustomCalendarWidget(
              callBack: (value) {
                //选择的时间
                _selectTime = value.split(" ").first;
                setState(() {});
              },
            ),
          );
        });
  }

  ///表格 1
  _getForm() {
    return Row(
      children: [
        //左边
        _getLeftForm(),
        //右边
        Expanded(
          child: _getRightForm(),
        ),
      ],
    );
  }

  ///左边表格 1.1
  _getLeftForm() {
    return Container(
      width: _fixedAreaWidth,
      child: Column(
        children: [
          //固定区域标题
          Container(
            width: _fixedAreaWidth,
            height: _fixedAreaHeight,
            child: _tabRowLeft(-1, _fixedAreas),
          ),
          //左边-上下滑动区域
          Expanded(
            child: ListView.builder(
              controller: _leftController,
              scrollDirection: Axis.vertical, //垂直滚动
              physics: BouncingScrollPhysics(),
              padding: EdgeInsets.zero,
              itemCount: _leftList.length,
              itemBuilder: (context, index) {
                return index == 0
                    ? _tabRowCUM(0, _leftList[0].toList1()[2], 3)
                    : _tabRowLeft(index, _leftList[index].toList1(), isTitle: false);
              },
            ),
          ),
        ],
      ),
    );
  }

  ///每行 1.1
  _tabRowLeft(
    int index, //下标
    List data, //数组
    {
    bool isTitle = true,
  }) {
    var widget;
    //始发=接收
    if (data[1] == data[2]) {
      widget = Row(
        children: [
          _tabRowCUM(index, "", 1),
          _tabRowCUM(index, data[2], 2),
        ],
      );
    }
    //始发!=接收
    else {
      widget = Row(
        children: data.asMap().keys.map((i) {
          String value = "";
          if (i == 0) {
            if (index == 1 + _count1 / 2 || index == 2 + _count1 + _count2 / 2) {
              value = data[i];
            } else if (index == -1) {
              value = data[i];
            }
          } else {
            value = data[i];
          }
          return Container(
            width: w(50),
            height: w(40),
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: i == 0 ? Color(0xffc2d7ff) : Colors.transparent,
              border: Border(
                right: BorderSide(color: i == 7 ? Colors.transparent : Color.fromRGBO(255, 255, 255, 0.53), width: w(1)),
                bottom: BorderSide(
                  color: index == 1 + _count1 && i == 0 ? Colors.white : Colors.transparent,
                  width: w(2),
                ),
              ),
            ),
            child: Text(
              value,
              textAlign: TextAlign.center,
              maxLines: 2,
              style: TextStyle(fontSize: sp(16), color: isTitle ? Color(0xd6333333) : Color(0xff333333)),
            ),
          );
        }).toList(),
      );
    }

    //返回
    return Container(
      decoration: BoxDecoration(
        color: index == -1
            ? Color(0xffc2d7ff)
            : index % 2 == 0
                ? Color.fromRGBO(236, 242, 250, 0.46)
                : Color(0xffecf2fa),
      ),
      child: widget,
    );
  }

  ///CUM 1.1
  _tabRowCUM(int index, String value, int count) {
    return Container(
      width: w(50) * count,
      height: w(40),
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: count == 3
            ? Color.fromRGBO(236, 242, 250, 0.46)
            : value.isEmpty
                ? Color(0xffc2d7ff)
                : index % 2 == 0
                    ? Colors.transparent
                    : Color(0xffecf2fa),
        border: Border(
          right: BorderSide(color: Color.fromRGBO(255, 255, 255, 0.53), width: w(1)),
        ),
      ),
      child: Text(
        value,
        textAlign: TextAlign.center,
        maxLines: 2,
        style: TextStyle(fontSize: sp(16), color: Color(0xff333333)),
      ),
    );
  }

  ///右边表格 1.2
  _getRightForm() {
    return Column(
      children: [
        //右边标题-左右滚动区域
        Container(
          width: _itemWidth * _rightTitles.length,
          height: _itemHeight,
          child: ListView.builder(
            controller: _rightTitleController,
            scrollDirection: Axis.horizontal, //水平滚动
            physics: BouncingScrollPhysics(),
            padding: EdgeInsets.zero,
            itemCount: _rightTitles.length,
            itemBuilder: (context, index) {
              return _tabItemRight(index, _rightTitles[index]);
            },
          ),
        ),
        //右边-上下-左右-滚动区域
        Expanded(
          child: ListView(
            controller: _rowController,
            scrollDirection: Axis.horizontal, //水平滚动
            physics: BouncingScrollPhysics(),
            padding: EdgeInsets.zero,
            children: [
              Container(
                width: _itemWidth * _rightList[0].toList2().length,
                child: ListView.builder(
                  controller: _columnController,
                  scrollDirection: Axis.vertical, //垂直滚动
                  physics: BouncingScrollPhysics(),
                  padding: EdgeInsets.zero,
                  itemCount: _rightList.length,
                  itemBuilder: (context, index) {
                    return _tabRowRight(index, _rightList[index].toList2(), isTitle: false);
                  },
                ),
              )
            ],
          ),
        ),
      ],
    );
  }

  ///每行 1.2
  _tabRowRight(
    int index, //下标
    List data, //数组
    {
    bool isTitle = true,
  }) {
    return Container(
      decoration: BoxDecoration(
        color: index == -1
            ? Color(0xffc2d7ff)
            : index % 2 == 0
                ? Color.fromRGBO(236, 242, 250, 0.46)
                : Color(0xffecf2fa),
      ),
      child: Row(
        children: data.asMap().keys.map((i) {
          return Container(
            width: w(50),
            height: w(40),
            alignment: Alignment.center,
            decoration: BoxDecoration(
              border: Border(
                right: BorderSide(color: i == 7 ? Colors.transparent : Color.fromRGBO(255, 255, 255, 0.53), width: w(1)),
              ),
            ),
            child: Text(
              data[i].toString(),
              textAlign: TextAlign.center,
              maxLines: 2,
              style: TextStyle(fontSize: sp(16), color: isTitle ? Color(0xd6333333) : Color(0xff333333)),
            ),
          );
        }).toList(),
      ),
    );
  }

  ///每个 1.2
  _tabItemRight(
    int i, //下标
    String value, //值
    {
    bool isTitle = true,
  }) {
    return Container(
      width: w(50),
      height: w(40),
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: Color(0xffc2d7ff),
        border: Border(
          right: BorderSide(color: i == 7 ? Colors.transparent : Color.fromRGBO(255, 255, 255, 0.53), width: w(1)),
        ),
      ),
      child: Text(
        value.toString(),
        textAlign: TextAlign.center,
        maxLines: 2,
        style: TextStyle(fontSize: sp(16), color: isTitle ? Color(0xd6333333) : Color(0xff333333)),
      ),
    );
  }

  //事件..

  ///初始化控制器配置
  _initController() {
    _fixedAreaWidth = w(150); //固定区域宽
    _fixedAreaHeight = w(40); //固定区域高
    _itemWidth = w(50); // item宽度
    _itemHeight = w(40); // item高度

    //水平滚动同步
    _horizontalControllers = LinkedScrollControllerGroup();
    _rightTitleController = _horizontalControllers?.addAndGet();
    _rowController = _horizontalControllers?.addAndGet();

    //垂直滚动同步
    _verticalControllers = LinkedScrollControllerGroup();
    _leftController = _verticalControllers?.addAndGet();
    _columnController = _verticalControllers?.addAndGet();
  }

  ///销毁控制器
  _disposeController() {
    _leftController?.dispose();
    _rightTitleController?.dispose();
    _rowController?.dispose();
    _columnController?.dispose();
  }

  //数据...

  ///数据
  _getData() {
    SendCarNumberList model = SendCarNumberList.fromMap2(sendCarNumberTestData);
    _leftList = model.sendCarList;
    _rightTitles = model.titleList;
    _rightList = model.sendCarList;
    _count1 = model.count1;
    _count2 = model.count2;
  }
}

linked_scroll_controller: ^0.2.0 #引入列表同步滚动

import 'package:flutter/material.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';

//固定标题的滑动
class TimeTablePage extends StatefulWidget {
  const TimeTablePage({Key key}) : super(key: key);

  @override
  _TimeTablePageState createState() => _TimeTablePageState();
}

class _TimeTablePageState extends State {
  int rowsCount = 100; //左边标题的个数
  int columnsCount = 30; //右边标题的个数

  double cellWidth = 80; // item宽度
  double cellHeight = 50; // item长度

  ScrollController leftController; //左边标题
  ScrollController topController; //右边标题
  ScrollController rowController; //数据

  List columnsController = [];
  LinkedScrollControllerGroup _verticalControllers;
  LinkedScrollControllerGroup _horizontalControllers;

  ///init
  @override
  void initState() {
    super.initState();
    //初始化控制器配置
    _initController();
  }

  ///dispose
  @override
  void dispose() {
    //销毁控制器
    _disposeController();
    super.dispose();
  }

  ///build
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("工时表"),
      ),
      body: _bodyWidget(),
    );
  }

  //界面...

  ///表格
  _bodyWidget() {
    return Row(
      children: [
        //左边
        Container(
          width: cellWidth,
          child: Column(
            children: [
              //时间 姓名
              Container(
                decoration: BoxDecoration(
                  color: Colors.blueGrey[100],
                  border: Border.all(color: Color(0xffeeeeee), width: 1),
                ),
                padding: EdgeInsets.only(left: 5.0, right: 5.0),
                height: cellHeight,
                width: cellWidth,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Container(
                      alignment: Alignment.topRight,
                      child: Text("时间"),
                    ),
                    Container(alignment: Alignment.bottomLeft, child: Text("姓名"))
                  ],
                ),
              ),
              //左边的标题
              Expanded(
                child: ListView.builder(
                  controller: leftController,
                  scrollDirection: Axis.vertical,
                  padding: EdgeInsets.all(0),
                  itemBuilder: (context, index) {
                    return Container(
                        decoration: BoxDecoration(
                          color: Colors.blueGrey[100],
                          border: Border.all(color: Color(0xffeeeeee), width: 1),
                        ),
                        height: cellHeight,
                        child: Center(child: Text("张${index + 1}")));
                  },
                  itemCount: rowsCount - 1,
                ),
              ),
            ],
          ),
        ),
        //右边
        Expanded(
          child: Column(
            children: [
              //右边标题
              Container(
                height: cellHeight,
                child: ListView.builder(
                  controller: topController,
                  padding: EdgeInsets.all(0),
                  scrollDirection: Axis.horizontal,
                  itemBuilder: (context, index) {
                    return Container(
                        decoration: BoxDecoration(
                          color: Colors.blueGrey[100],
                          border: Border.all(color: Color(0xffeeeeee), width: 1),
                        ),
                        width: cellWidth,
                        child: Center(child: Text("8月${index + 1}日")));
                  },
                  itemCount: columnsCount,
                ),
              ),
              //右边数据
              Expanded(
                child: ListView.builder(
                  controller: rowController,
                  padding: EdgeInsets.all(0),
                  scrollDirection: Axis.horizontal,
                  itemBuilder: (context, index) {
                    return Container(
                      width: cellWidth,
                      child: ListView.builder(
                        controller: columnsController[index],
                        scrollDirection: Axis.vertical,
                        shrinkWrap: true,
                        padding: EdgeInsets.all(0),
                        itemBuilder: (context, innerIndex) {
                          return Container(height: cellHeight, child: Center(child: Text("$innerIndex, $index")));
                        },
                        itemCount: rowsCount - 1,
                      ),
                    );
                  },
                  itemCount: columnsCount,
                ),
              )
            ],
          ),
        ),
      ],
    );
  }

  //事件...

  ///初始化控制器配置
  _initController() {
    //水平同步滚动
    _horizontalControllers = LinkedScrollControllerGroup();
    topController = _horizontalControllers?.addAndGet();
    rowController = _horizontalControllers?.addAndGet();

    //垂直同步滚动
    _verticalControllers = LinkedScrollControllerGroup();
    leftController = _verticalControllers?.addAndGet();
    for (var i = 0; i < columnsCount; i++) {
      ScrollController columnController = _verticalControllers?.addAndGet();
      if (columnController != null) {
        columnsController.add(columnController);
      }
    }
  }

  ///销毁控制器
  _disposeController() {
    leftController?.dispose();
    topController?.dispose();
    rowController?.dispose();
    for (var controller in columnsController) {
      controller.dispose();
    }
  }
}

参考:
https://www.jianshu.com/p/1543c5fda631

你可能感兴趣的:(20.flutter-表格)