flutter 实现可横滑table表格

需求:实现可横滑、竖滑动表格,保持第一列不动

git 链接:https://gitee.com/niliusha/flutter_demo.git

参考链接

在这里插入图片描述

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fuxi_knowledge/constants/color_constant.dart';

import '../../../../../constants/route_constant.dart';
import '../../../../../router/router_delegate.dart';

class ApplicationScrollTablePage extends StatefulWidget {
  final Map<String, dynamic>? originalParams;

  const ApplicationScrollTablePage({Key? key, this.originalParams})
      : super(key: key);

  
  State<ApplicationScrollTablePage> createState() =>
      _ApplicationScrollTablePageState();
}

class _ApplicationScrollTablePageState
    extends State<ApplicationScrollTablePage> {
  final List<String> _titleList = [
    "标题1",
    "标题2",
    "标题3",
    "标题4",
    "标题5",
    "标题6",
    "标题7"
  ];
  final List<String> _columnList = [];
  final double _leftWidth = 30.w;
  final double _cellWidth = 100.w;
  final double _cellHeight = 28.h;
  final ScrollController _titleController = ScrollController();
  final ScrollController _contentController = ScrollController();

  
  void initState() {
    super.initState();
    _titleController.addListener(_updateContent);
    _contentController.addListener(_updateTitle);
    //测试数据
    for (int i = 0; i < 10; i++) {
      _columnList.add(i.toString());
    }
  }

  void _updateTitle() {
    if (_titleController.offset != _contentController.offset) {
      _titleController.jumpTo(_contentController.offset);
    }
  }

  void _updateContent() {
    if (_contentController.offset != _titleController.offset) {
      _contentController.jumpTo(_titleController.offset);
    }
  }

  
  void dispose() {
    _titleController.removeListener(_updateContent);
    _contentController.removeListener(_updateTitle);
    super.dispose();
  }

  Container _buildTitleContainer(int i) {
    return Container(
      decoration: const BoxDecoration(
          color: colorWhite51,
          border: Border(
            // bottom: BorderSide(color: tableTitleLineColor, width: 1),
              right: BorderSide(color: tableTitleLineColor, width: 1))),
      alignment: Alignment.center,
      width: _cellWidth,
      height: _cellHeight,
      child: Text(
        _titleList[i],
        style: TextStyle(color: Colors.white, fontSize: 12.sp),
      ),
    );
  }

  _buildRightTitle() {
    List<Widget> list = [];
    for (int i = 0; i < _titleList.length; i++) {
      list.add(_buildTitleContainer(i));
    }
    return list;
  }

  _buildRightContent(int index) {
    List<Widget> list = [];
    for (int i = 0; i < _titleList.length; i++) {
      list.add(Container(
        alignment: const Alignment(0, 0),
        decoration: const BoxDecoration(
            border: Border(
                bottom: BorderSide(color: tableLineColor, width: 1),
                right: BorderSide(color: tableLineColor, width: 1))),
        width: _cellWidth,
        height: _cellHeight,
        child: Text(
          "行$index${i + 1}",
          style: TextStyle(color: color153, fontSize: 10.sp),
        ),
      ));
    }
    return list;
  }

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          children: [
            Container(
              margin: EdgeInsets.only(top: 12.h),
              decoration: const BoxDecoration(
                  color: colorWhite51,
                  border: Border(
                    // bottom: BorderSide(color: tableTitleLineColor, width: 1),
                      right: BorderSide(color: tableTitleLineColor, width: 1))),
              width: _leftWidth,
              height: _cellHeight,
              alignment: Alignment.center,
              // child: Text(
              //   '标题',
              //   style: TextStyle(color: Colors.white, fontSize: 12.sp),
              // ),
            ),
            Expanded(
                child: Container(
                  margin: EdgeInsets.only(top: 12.h),
                  width: _titleList.length * _cellWidth,
                  child: SingleChildScrollView(
                    controller: _titleController,
                    scrollDirection: Axis.horizontal,
                    child: Row(
                      children: _buildRightTitle(),
                    ),
                  ),
                ))
          ],
        ),
        Expanded(
            child: SingleChildScrollView(
              child: Column(
                children: [
                  Row(
                    children: [
                      SizedBox(
                        width: _leftWidth,
                        child: ListView.builder(
                          shrinkWrap: true,
                          physics: const NeverScrollableScrollPhysics(),
                          itemBuilder: (context, index) {
                            return GestureDetector(
                                onTap: () {},
                                child: Container(
                                    alignment: const Alignment(0, 0),
                                    decoration: const BoxDecoration(
                                        border: Border(
                                            bottom: BorderSide(
                                                color: color135_40, width: 1),
                                            right: BorderSide(
                                                color: color135_40, width: 1))),
                                    width: _cellWidth,
                                    height: _cellHeight,
                                    child: Icon(Icons.expand,
                                        color: color153, size: 20.r)));
                          },
                          itemCount: _columnList.length,
                        ),
                      ),
                      Expanded(
                          child: SingleChildScrollView(
                            controller: _contentController,
                            scrollDirection: Axis.horizontal,
                            child: SizedBox(
                              width: _titleList.length * _cellWidth,
                              child: ListView.builder(
                                itemCount: _columnList.length,
                                shrinkWrap: true,
                                physics: const NeverScrollableScrollPhysics(),
                                itemBuilder: (context, index) {
                                  return GestureDetector(
                                    onTap: () {},
                                    child: Row(
                                      children: _buildRightContent(index),
                                    ),
                                  );
                                },
                              ),
                              // ),
                            ),
                          ))
                    ],
                  ),
                ],
              ),
            ))
      ],
    );
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter 目前还没有内置的表格控件,但是可以使用 `Table` 和 `TableCell` 来实现表格合并单元格。 具体实现步骤如下: 1. 定义表格数据和合并单元格的规则。 ```dart List<List<String>> tableData = [ ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ['A3', 'B3', 'C3'], ['A4', 'B4', 'C4'], ]; Map<int, List<TableCell>> mergedCells = { 0: [ TableCell( child: Text('A1'), rowSpan: 2, columnSpan: 2, ), null, TableCell( child: Text('C1'), rowSpan: 2, ), ], }; ``` 2. 根据表格数据和合并单元格的规则构建表格控件。 ```dart Table( children: tableData.asMap().entries.map((row) { int rowIndex = row.key; List<String> rowData = row.value; List<TableCell> cells = rowData.asMap().entries.map((cell) { int columnIndex = cell.key; String cellData = cell.value; if (mergedCells.containsKey(rowIndex) && mergedCells[rowIndex][columnIndex] != null) { // 如果当前单元格需要合并,则返回合并单元格的配置 return mergedCells[rowIndex][columnIndex]; } else { // 否则返回普通单元格 return TableCell( child: Text(cellData), ); } }).toList(); return TableRow( children: cells, ); }).toList(), ) ``` 3. 运行程序,即可看到合并单元格的表格效果。 完整代码如下: ```dart import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { List<List<String>> tableData = [ ['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ['A3', 'B3', 'C3'], ['A4', 'B4', 'C4'], ]; Map<int, List<TableCell>> mergedCells = { 0: [ TableCell( child: Text('A1'), rowSpan: 2, columnSpan: 2, ), null, TableCell( child: Text('C1'), rowSpan: 2, ), ], }; return MaterialApp( title: 'Flutter Demo', home: Scaffold( appBar: AppBar( title: Text('Table with merged cells'), ), body: Center( child: Table( children: tableData.asMap().entries.map((row) { int rowIndex = row.key; List<String> rowData = row.value; List<TableCell> cells = rowData.asMap().entries.map((cell) { int columnIndex = cell.key; String cellData = cell.value; if (mergedCells.containsKey(rowIndex) && mergedCells[rowIndex][columnIndex] != null) { // 如果当前单元格需要合并,则返回合并单元格的配置 return mergedCells[rowIndex][columnIndex]; } else { // 否则返回普通单元格 return TableCell( child: Text(cellData), ); } }).toList(); return TableRow( children: cells, ); }).toList(), ), ), ), ); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值