Flutter 上下左右滚动Table

Flutter 上下左右滚动Table

在这里插入图片描述

实现功能

  1. 可以上下左右滚动
  2. 可修改多个参数配置
  3. 实现单独选中某个格子

适用性

参数:

  double rowWidth; //单个表宽
  double rowHeight; //表格高

  List<String> titleList = List(); //标题  ["职责", "工作内容", "年度目标", "关联部门", "备注", "1"];
  List<List<String>> contentList = List(); //内容列表
  List<String> selectList = List(); //选中列表  ["0,1","1,2"]

  Color titleBackgroundColor; //标题背景颜色
  Color titleTextColor; //标题字体颜色
  Color contentBackgroundColor; //列表背景颜色
  Color contentTextColor; //列表字体颜色
  Color leftFirstTextColor; //左边第一列字体颜色
  Color leftFirstBackgroundColor; //左边第一列背景颜色
  Color borderColor; //边框颜色
  Color allSelectColor; //所有选中颜色
  Color selectTextColor; //选中字体颜色

  double titleFontSize; //标题字体大小
  double contentFontSize; //列表字体大小
  double leftFirstFontSize; //左边第一列字体大小
  double selectFontSize; //选中字体大小

使用

import 'package:flutter_sams/config/export/export.dart';
import 'package:flutter_sams/view/table_widget.dart';

class TablePage extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _TablePageState();
  }

}

class _TablePageState extends State<TablePage>{

  List<String> titleList = ['日期','项目','日期','项目'];

  //列表所有数据
  List<List<String>> allList = List();
  List<String> contentList = List();
  List<List<String>> _getContentList() {
    for (int i = 1; i < 20; i++) {
      contentList = List();
      contentList.add("202$i");
      contentList.add("学习2222222255555555555555553333333332$i");
      contentList.add("202103$i");
      contentList.add("202103$i");
      allList.add(contentList);
    }
    return allList;
  }


  List<String> _getSelectList(){
    List<String> selectList = List();
    selectList.add("2,5");
    selectList.add("0,1");
    selectList.add("3,0");
    return selectList;
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('Table'),
      ),
      body: Container(
        child: TableWidget(titleList,_getContentList(),selectList: _getSelectList(),
        onTap: (x,y){
          print("外部  x=$x y=$y");
        }),
      ),
    );
  }
}

Widget全部代码

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_sams/config/export/export.dart';

class TableWidget extends StatelessWidget {
  double rowWidth; //单个表宽
  double rowHeight; //表格高

  List<String> titleList = List(); //标题  ["职责", "工作内容", "年度目标", "关联部门", "备注", "1"];
  List<List<String>> contentList = List(); //内容列表
  List<String> selectList = List(); //选中列表  ["0,1","1,2"]

  Color titleBackgroundColor; //标题背景颜色
  Color titleTextColor; //标题字体颜色
  Color contentBackgroundColor; //列表背景颜色
  Color contentTextColor; //列表字体颜色
  Color leftFirstTextColor; //左边第一列字体颜色
  Color leftFirstBackgroundColor; //左边第一列背景颜色
  Color borderColor; //边框颜色
  Color allSelectColor; //所有选中颜色
  Color selectTextColor; //选中字体颜色

  double titleFontSize; //标题字体大小
  double contentFontSize; //列表字体大小
  double leftFirstFontSize; //左边第一列字体大小
  double selectFontSize; //选中字体大小

  Function onTap;

  TableWidget(this.titleList, this.contentList,
      {this.rowWidth = 100.0,
      this.rowHeight = 48.0,
      this.titleBackgroundColor = Colors.greenAccent,
      this.titleTextColor = Colors.blueAccent,
      this.contentBackgroundColor = Colors.white,
      this.contentTextColor = Colors.black87,
      this.titleFontSize = 12,
      this.contentFontSize = 12,
      this.leftFirstBackgroundColor = Colors.white,
      this.leftFirstTextColor = Colors.black87,
      this.leftFirstFontSize = 12,
      this.selectList,
      this.borderColor = Colors.black54,
      this.allSelectColor = Colors.redAccent,
      this.selectTextColor = Colors.black87,
      this.selectFontSize = 12,
      this.onTap});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: _Table(
          this.rowWidth,
          this.rowHeight,
          this.titleList,
          this.contentList,
          this.titleBackgroundColor,
          this.titleTextColor,
          this.contentBackgroundColor,
          this.contentTextColor,
          this.titleFontSize,
          this.contentFontSize,
          this.leftFirstBackgroundColor,
          this.leftFirstTextColor,
          this.leftFirstFontSize,
          this.selectList,
          this.borderColor,
          this.allSelectColor,
          this.selectTextColor,
          this.selectFontSize,
          this.onTap),
    );
  }
}

class _Table extends StatefulWidget {
  double rowWidth; //单个表宽
  double rowHeight; //表格高

  List<String> titleList; //标题
  List<List<String>> contentList;
  List<String> selectList; //选中列表  ["0,1","1,2"]

  Color titleBackgroundColor;
  Color titleTextColor;
  Color contentBackgroundColor; //列表背景颜色
  Color contentTextColor;
  Color leftFirstTextColor; //左边第一列字体颜色
  Color leftFirstBackgroundColor; //左边第一列背景颜色
  Color borderColor; //边框颜色
  Color allSelectColor; //所有选中颜色
  Color selectTextColor; //选中字体颜色

  double titleFontSize; //标题字体大小
  double contentFontSize; //列表字体大小
  double leftFirstFontSize; //左边第一列字体大小
  double selectFontSize; //选中字体大小

  Function onTap;

  _Table(
      this.rowWidth,
      this.rowHeight,
      this.titleList,
      this.contentList,
      this.titleBackgroundColor,
      this.titleTextColor,
      this.contentBackgroundColor,
      this.contentTextColor,
      this.titleFontSize,
      this.contentFontSize,
      this.leftFirstBackgroundColor,
      this.leftFirstTextColor,
      this.leftFirstFontSize,
      this.selectList,
      this.borderColor,
      this.allSelectColor,
      this.selectTextColor,
      this.selectFontSize,
      this.onTap);

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

class _TableState extends State<_Table> {
  //定义可控制滚动组件
  ScrollController firstColumnController = ScrollController();
  ScrollController thirdColumnController = ScrollController();

  ScrollController firstRowController = ScrollController();
  ScrollController secondedRowController = ScrollController();

  //创建第一列行
  // double numRowWidth = 100.0; //单个表宽
  // double numRowHeight = 48.0; //表格高

  // Color titleBackgroundColor = Color(0xFF88DFE4);
  // Color titleTextColor = Colors.blueAccent;

  //顶部标题
  // List<String> titleList = ["职责", "工作内容", "年度目标", "关联部门", "备注", "1"];

  //列表所有数据
  List<List<String>> allList = List();
  List<String> contentList = List();

  //左边第一列数据--不包含顶部标题
  List<String> leftList = List();

  //右边所有数据--不包含顶部标题和第一列数据
  List<List<String>> rightList = List();
  List<String> rightContentList = List();

  // List<String> selectList = List();

  List<List<String>> _getContentList() {
    for (int i = 0; i < 20; i++) {
      contentList = List();
      contentList.add("软件质量管理$i");
      contentList.add("学习$i");
      contentList.add("成为顶尖开发$i");
      contentList.add("信息技术事业部$i");
      contentList.add("加油$i");
      contentList.add("随意添加$i");
      allList.add(contentList);
    }
    return allList;
  }

  void _getTwoList(List<List<String>> contentList) {
    leftList.clear();
    rightList.clear();
    rightList.clear();
    contentList.forEach((itList) {
      rightContentList = List();
      for (int i = 0; i < itList.length; i++) {
        if (i == 0) {
          leftList.add(itList[i]);
        } else {
          rightContentList.add(itList[i]);
        }
      }
      rightList.add(rightContentList);
    });
  }

  List<int> xList = List();
  List<int> yList = List();

  ///第一列数据
  List<TableRow> _buildTableColumnOne() {
    List<TableRow> returnList = List();
    for (int i = 0; i < leftList.length; i++) {
      returnList.add(_buildSingleColumnOne(i, leftList[i], leftList.length,
          isSelect: widget.selectList.contains("0,$i")));
    }
    return returnList;
  }

  //创建tableRows
  List<TableRow> _buildTableRow() {
    List<TableRow> returnList = new List();
    for (int j = 0; j < rightList.length; j++) {
      returnList.add(_buildSingleRow(j, rightList[j], false)); //添加行
    }
    return returnList;
  }

  ///第一行标题  创建单行
  List<TableRow> _buildTableOneRow() {
    List<TableRow> returnList = new List();
    for (int j = 0; j < 1; j++) {
      returnList.add(_buildSingleRow(j, widget.titleList, true)); //添加行
    }
    return returnList;
  }

  //创建第一列tableRow
  TableRow _buildSingleColumnOne(int index, String text, int totalLength,
      {bool isSelect = false}) {
    return TableRow(children: [
      _buildSideBox(index, text, false, isLeftFirst: true, isSelect: isSelect),
    ]);
  }

  //创建一行tableRow
  TableRow _buildSingleRow(int index, List<String> textList, bool isTitle) {
    return TableRow(children: [
      for (int i = 0;
          i < (isTitle ? textList.length - 1 : textList.length);
          i++)
        isTitle
            ? _buildSideBox(i, textList[i + 1], true)
            : _buildSideBox(i, textList[i], false,
                xx: index,
                isSelect: widget.selectList.contains("${i + 1},$index")),
    ]);
  }

  //创建单个表格
  Widget _buildSideBox(int index, String title, bool isTitle,
      {bool isLeftFirst = false, int xx, bool isSelect = false}) {
    return Container(
      color: isTitle
          ? widget.titleBackgroundColor
          : (isLeftFirst
              ? isSelect
                  ? widget.allSelectColor
                  : widget.leftFirstBackgroundColor
              : isSelect
                  ? widget.allSelectColor
                  : widget.contentBackgroundColor),
      child: InkWell(
        child: SizedBox(
            height: widget.rowHeight,
            child: Container(
              alignment: Alignment.center,
              decoration: BoxDecoration(
                  border: Border(
                bottom: BorderSide(width: 0.33, color: widget.borderColor),
                top: BorderSide(width: 0.33, color: widget.borderColor),
                right: BorderSide(width: 0.33, color: widget.borderColor),
                left: BorderSide(width: 0.33, color: widget.borderColor),
              )),
              child: Text(
                title,
                // maxLines: 1,
                // overflow: TextOverflow.ellipsis,
                style: TextStyle(
                    fontSize: isTitle
                        ? widget.titleFontSize
                        : (isLeftFirst
                            ? isSelect
                                ? widget.selectFontSize
                                : widget.leftFirstFontSize
                            : isSelect
                                ? widget.selectFontSize
                                : widget.contentFontSize),
                    color: isTitle
                        ? widget.titleTextColor
                        : (isLeftFirst
                            ? isSelect
                                ? widget.selectTextColor
                                : widget.leftFirstTextColor
                            : isSelect
                                ? widget.selectTextColor
                                : widget.contentTextColor)),
              ),
            )),
        onTap: () {
          if (widget.onTap != null) {
            int x = 0;
            int y = 0;
            if (isLeftFirst) {
              x = 0;
              y = index;
              // print("&&x=0 y=$index");

            } else {
              y = xx;
              x = index + 1;
              // print("&&x=$x y=$y");
            }
            widget.onTap(x, y);
          }
        },
      ),
    );
  }

  @override
  void initState() {
    super.initState();

    // _getTwoList(_getContentList());
    _getTwoList(widget.contentList);

    //监听第一列变动
    firstColumnController.addListener(() {
      if (firstColumnController.offset != thirdColumnController.offset) {
        thirdColumnController.jumpTo(firstColumnController.offset);
      }
    });

    //监听第三列变动
    thirdColumnController.addListener(() {
      if (firstColumnController.offset != thirdColumnController.offset) {
        firstColumnController.jumpTo(thirdColumnController.offset);
      }
    });

    //监听第一行变动
    firstRowController.addListener(() {
      if (firstRowController.offset != secondedRowController.offset) {
        secondedRowController.jumpTo(firstRowController.offset);
      }
    });

    //监听第二行变动
    secondedRowController.addListener(() {
      if (firstRowController.offset != secondedRowController.offset) {
        firstRowController.jumpTo(secondedRowController.offset);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: MediaQuery.removePadding(
      removeTop: true,
      context: context,
      child: NotificationListener(
        //表格
        child: Container(
          // padding: EdgeInsets.only(right: 8, left:8, top: 8, bottom: 8),
          // margin: EdgeInsets.only(right: 16,left:16),
          // height: 209,
          // width:375,
          // color:Colors.lightGreen,
          child: Row(
            children: [
              //前两列
              Container(
                width: widget.rowWidth,
                // height:200,
                child: Column(
                  children: [
                    Table(
                      children: [
                        TableRow(
                          children: [
                            Container(
                              decoration: BoxDecoration(
                                border: Border(
                                  bottom: BorderSide(
                                      width: 0.33, color: widget.borderColor),
                                  top: BorderSide(
                                      width: 0.33, color: widget.borderColor),
                                  right: BorderSide(
                                      width: 0.33, color: widget.borderColor),
                                  left: BorderSide(
                                      width: 0.33, color: widget.borderColor),
                                ),
                              ),
                              child: Container(
                                height: widget.rowHeight - 0.33,
                                color: widget.titleBackgroundColor,
                                // padding: EdgeInsets.all(10),
                                child: Center(
                                  child: Text(
                                    widget.titleList[0],
                                    textAlign: TextAlign.center,
                                    style: TextStyle(
                                        color: widget.titleTextColor,
                                        fontSize: widget.titleFontSize),
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                    //SingleChildScrollView(
                    Expanded(
                      child: ListView(
                        controller: firstColumnController,
                        children: [
                          Table(children: _buildTableColumnOne()),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
              //其余列
              Expanded(
                child: Container(
                  // width: 200,
                  child: Column(children: [
                    Container(
                      alignment: Alignment.topLeft,
                      child: SingleChildScrollView(
                          scrollDirection: Axis.horizontal, //horizontal
                          controller: firstRowController,
                          child: Container(
                            child: Table(children: _buildTableOneRow()),
                            width: (widget.rowWidth) *
                                (widget.titleList.length - 1), //设置列的行宽
                          )),
                    ),
                    Expanded(
                      child: ListView(
                        controller: thirdColumnController,
                        children: [
                          SingleChildScrollView(
                            controller: secondedRowController,
                            scrollDirection: Axis.horizontal, //horizontal
                            child: Row(
                              children: [
                                Container(
                                  child: Table(children: _buildTableRow()),
                                  width: (widget.rowWidth) *
                                      (widget.titleList.length - 1), //设置列的行宽
                                )
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                  ]),
                ),
              ),
            ],
          ),
        ),
      ),
    ));
  }

  @override
  void dispose() {
    // TODO: implement dispose
    firstColumnController?.dispose();
    thirdColumnController?.dispose();
    firstRowController?.dispose();
    secondedRowController?.dispose();
    super.dispose();
  }
}

存在缺陷

表格宽度暂时无法自动适配,只能自己传参修改

引用

感谢这位老铁的分享,此组件是在这基础上进行完善。
[https://blog.csdn.net/zzy123zzy123_/article/details/108867596]

结尾

欢迎各位留言

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值