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
相关产品推荐
相关产品推荐

