You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何让单个DataCell填充完整宽度?

问题描述

我想实现Flutter单个DataCell灰显的效果,以此提示用户该单元格需留空。目前已实现填充DataCell的高度,但宽度无法填满整个单元格。

当前代码片段

_data[i][newColumn] = Container(
 width: double.infinity,
 height: double.infinity,
 color: Colors.grey,
  child: Text(''));

当前效果

最右侧的单元格仅填满高度空间:
效果截图

完整代码

import 'dart:convert';
import 'dart:ui';
import 'package:http/http.dart';
import 'package:flutter/material.dart';

class InspectionSheet extends StatefulWidget {
  const InspectionSheet({Key? key}) : super(key: key);

  @override
  State<InspectionSheet> createState() => _InspectionSheetState();
}

class _InspectionSheetState extends State<InspectionSheet> {
  GlobalKey<FormState> _formKey = new GlobalKey();

  bool validate = false;
  TextEditingController ctrlsampleSize = TextEditingController();

  final List<Map<String, dynamic>> _data = [
    {
      //"checkitemID": "0",
      "Ballooning No": "1",
      "Datatype": "1",
      "Specifications": ".325+-0.020",
      "Tool": "CALIPER",
      "LSL": "0.305",
      "Target": "2",
      "USL": "0.325",
      "Tol-": "0.02",
      "Tol+": "0.02",
      "Image": "",
      "WI": ""
    },
    {
      //"checkitemID": "0",
      "Ballooning No": "2",
      "Datatype": "2",
      "Specifications": ".325+-0.020",
      "Tool": "CALIPER",
      "LSL": "0.305",
      "Target": "2",
      "USL": "0.325",
      "Tol-": "0.02",
      "Tol+": "0.02",
      "Image": "",
      "WI": ""
    },
   
  ];

  late List<String> _columnNames;
  String _selectedValue = 'PASS';

  void startbutton() {
    validateEmpty();
    if (_formKey.currentState!.validate()) {
      addDataCol();
    }
  }

  void validateEmpty() {
    ctrlsampleSize.text.isEmpty ? validate = false : validate = true;
  }

  void addDataCol() {
    int colNo = int.parse(ctrlsampleSize.text);
    if (colNo < 1) {
      return;
    }

    setState(() {
      for (var i = 1; i <= colNo; i++) {
        _addColumn('Data $i');
      }
    });
  }

  void _addColumn(String newColumn) {
    if (_columnNames.contains(newColumn)) {
      return;
    }
    setState(() {
      for (var i = 0; i <= _data.length - 1; i++) {
        if (_data[i]['Datatype'] == '1') {
          _data[i][newColumn] = TextFormField();
        } else if (_data[i]['Datatype'] == '2') {
          _data[i][newColumn] = DropdownButton<String>(
              value: _selectedValue,
              icon: const Icon(Icons.arrow_drop_down_circle_outlined),
              elevation: 16,
              underline: Container(
                height: 2,
                color: Colors.blue,
              ),
              onChanged: (newValue) {
                setState(() {
                  _selectedValue = newValue!;
                });
              },
              items: [
                DropdownMenuItem(
                  value: 'PASS',
                  child: const Text('PASS'),
                  onTap: () {
                    _selectedValue = 'PASS';
                  },
                ),
                DropdownMenuItem(
                  value: 'FAIL',
                  child: const Text('FAIL'),
                  onTap: () {
                    _selectedValue = 'FAIL';
                  },
                ),
                DropdownMenuItem(
                  value: 'UAI',
                  child: const Text('UAI'),
                  onTap: () {
                    _selectedValue = 'UAI';
                  },
                ),
                DropdownMenuItem(
                  value: 'NA',
                  child: const Text('NA'),
                  onTap: () {
                    _selectedValue = 'NA';
                  },
                )
              ]);
        } else if (_data[i]['Datatype'] == '3') {
          if (newColumn == 'Data 1') {
            _data[i][newColumn] = TextButton(
                onPressed: () {
                  _displayTextInputDialog(context);
                },
                child: const Text('-'));
          } else {
            _data[i][newColumn] = Container(
                width: double.infinity,
                height: double.infinity,
                color: Colors.grey,
                child: Text(''));
          }
        } else {
          _data[i][newColumn] = TextButton(
              onPressed: () {
                _displayTextInputDialog(context);
              },
              child: const Text('-'));
        }
      }
      _columnNames.add(newColumn);
    });
  }

  @override
  void initState() {
    // 原代码中dateInput未定义,此处保留结构注释
    // dateInput.text = "";
    _columnNames = _data[0].keys.toList();
    super.initState();
    ctrlsampleSize.addListener(() {});
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: [
          Form(
            child: Row(
              children: [
                Container(
                  width: MediaQuery.of(context).size.width,
                  height: 210,
                  child: Form(
                    key: _formKey,
                    child: ListView(
                      children: [
                        Row(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          children: [
                            Container(
                              width: 200,
                              height: 200,
                              child: Column(
                                children: <Widget>[
                                  TextFormField(
                                    controller: ctrlsampleSize,
                                    validator: ((value) {
                                      if (value == null || value.isEmpty) {
                                        return 'Please enter sample size';
                                      }
                                      return null;
                                    }),
                                  ),
                                ],
                              ),
                            ),
                            
                            Padding(
                              padding: const EdgeInsets.fromLTRB(0, 5, 0, 0),
                              child: Container(
                                width: 400,
                                height: 200,
                                decoration: BoxDecoration(
                                    border: Border.all(color: Colors.black),
                                    image: DecorationImage(
                                      image: const AssetImage('images/Test1.jpg'),
                                      fit: BoxFit.fill,
                                    )),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
                Container(
                  child: Container(
                    child: Center(
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: <Widget>[
                          Padding(
                            padding: const EdgeInsets.fromLTRB(15, 15, 860, 0),
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.start,
                              children: const [
                                Text(
                                  "Total Parameter : 6",
                                  textAlign: TextAlign.left,
                                  style: TextStyle(
                                      fontSize: 16, fontWeight: FontWeight.bold),
                                ),
                              ],
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
                            child: ElevatedButton(
                              onPressed: () => startbutton(),
                              child: const Text('Start'),
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
                            child: ElevatedButton(
                              onPressed: () {},
                              child: const Text('Reset'),
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.fromLTRB(15, 15, 8, 0),
                            child: ElevatedButton(
                              onPressed: () {},
                              child: const Text('Save'),
                            ),
                          ),
                        ],
                      ),
                    ),
                  )),
              ],
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: SingleChildScrollView(
                scrollDirection: Axis.vertical,
                child: DataTable(
                  headingRowHeight: 30,
                  border: TableBorder.all(
                    color: Colors.grey,
                  ),
                  headingRowColor: MaterialStateColor.resolveWith(
                      (states) => Colors.lightBlue),
                  headingTextStyle: const TextStyle(
                      color: Colors.white, fontWeight: FontWeight.w800),
                  columns: _columnNames.map((columnName) {
                    return DataColumn(
                      label: Text(
                        columnName,
                      ),
                    );
                  }).toList(),
                  rows:
                      _data.map((row) {
                    return DataRow(
                        cells: row.values.map((cellValue) {
                      try {
                        return DataCell(
                          cellValue,
                          onTap: () {},
                        );
                      } catch (e) {
                        return DataCell(Text(cellValue));
                      }
                    }).toList());
                  }).toList(),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  // 原代码中未实现的方法,保留占位
  void _displayTextInputDialog(BuildContext context) {}
}
解决方案

问题根源是DataCell默认带有内边距,导致子组件的width: double.infinity无法填满整个单元格宽度。可以通过以下两种方式解决:

方法1:移除DataCell默认内边距(推荐)

在创建DataCell时,添加padding: EdgeInsets.zero消除默认内边距限制,确保子容器完全填满单元格:

return DataCell(
  Container(
    width: double.infinity,
    height: double.infinity,
    color: Colors.grey,
    child: const Text(''),
  ),
  onTap: () {},
  padding: EdgeInsets.zero, // 关键:移除默认内边距
);

方法2:优化Container配置

如果不想修改DataCell的创建逻辑,可以给Container添加alignment属性,同时确保父组件约束生效:

_data[i][newColumn] = Container(
  width: double.infinity,
  height: double.infinity,
  color: Colors.grey,
  alignment: Alignment.center, // 可选优化,让内容居中
  child: const Text(''),
);

内容的提问来源于stack exchange,提问作者nrain3112

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:50:26