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

Flutter中DataTable添加列后RenderFlex右侧溢出的解决方法

Flutter DataTable添加列后溢出问题解决

问题说明

给Flutter应用的DataTable新增列后,出现错误提示:A RenderFlex overflowed by 71 pixels on the right.,需要让表格列适配屏幕尺寸,解决溢出问题。

错误截图:
错误截图

原相关代码:

// For CircularProgressIndicator.
bool visible = false;
String? dropdownValue = 'Hoy';

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: new AppBar(
      backgroundColor: Colors.black87,
      leading: BackButton(
        color: Colors.white,
        onPressed: () {
          Navigator.push(context,
              MaterialPageRoute(builder: (context) => HomePage(0, 0)));
        },
      ),
      title: new Text("Planilla de horarios"),
    ),
    body: (!visible)
        ? Container(
            color: Colors.white,
            height: MediaQuery.of(context).size.height,
            child: SingleChildScrollView(
              child: Column(
                mainAxisSize: MainAxisSize.max,
                children: <Widget>[
                  Container(
                    color: Colors.grey,
                    child: Row(children: <Widget>[
                      FutureBuilder<String>(
                          future: globals.SharedPreferencesHelper
                              .getDataFilterDebt(),
                          builder: (context, snapshot) {
                            if (snapshot.hasData) {
                              return Expanded(
                                child: Row(
                                  children: <Widget>[
                                    Expanded(
                                      flex: 2,
                                      child: DropdownButton<String>(
                                        value: dropdownValue,
                                        icon: Icon(Icons.arrow_downward),
                                        iconSize: 24,
                                        iconEnabledColor: Colors.white,
                                        elevation: 16,
                                        style: TextStyle(color: Colors.black),
                                        underline: Container(
                                          height: 0,
                                          color: Colors.black,
                                        ),
                                        onChanged: (String? newValue) {
                                          setState(() {
                                            dropdownValue = newValue;
                                          });
                                        },
                                        items: <String>['Hoy', 'Mañana']
                                            .map<DropdownMenuItem<String>>(
                                                (String value) {
                                          return DropdownMenuItem<String>(
                                            value: value,
                                            child: Text(value),
                                          );
                                        }).toList(),
                                      ),
                                    ),
                                    Container(
                                      margin:
                                          const EdgeInsets.only(right: 10.0),
                                      color: Colors.grey,
                                      child: new Row(
                                          mainAxisAlignment:
                                              MainAxisAlignment.center,
                                          children: <Widget>[
                                            FlatButton(
                                              child: Text("Buscar"),
                                              color: Color(0xFF1F1F1F),
                                              textColor: Colors.white,
                                              padding: EdgeInsets.only(
                                                  left: 2,
                                                  right: 2,
                                                  top: 2,
                                                  bottom: 2),
                                              shape: RoundedRectangleBorder(
                                                  borderRadius:
                                                      BorderRadius.circular(
                                                          5)),
                                              onPressed: () {
                                                obtenerDetallesTecnicasImplantes(
                                                    dropdownValue.toString());

                                                setState(() {});
                                              },
                                            ),
                                          ]),
                                    ),
                                  ],
                                ),
                              );
                            } else if (snapshot.hasError) {
                              return Image.asset("images/fundo_login.jpg");
                            } else {
                              return Container(
                                margin: EdgeInsets.only(top: 18),
                                child: Row(
                                  crossAxisAlignment:
                                      CrossAxisAlignment.center,
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: <Widget>[
                                    Visibility(
                                        child: Container(
                                      margin: EdgeInsets.only(bottom: 17.5),
                                      child: CircularProgressIndicator(
                                        valueColor:
                                            AlwaysStoppedAnimation<Color>(
                                                Colors.black),
                                      ),
                                      height: 20,
                                      width: 20,
                                    )),
                                  ],
                                ),
                              );
                            }
                          }),
                    ]),
                  ),
                  DataTable(
                    columns: [
                      DataColumn(label: Text('Hora')),
                      DataColumn(label: Text('Sector')),
                      DataColumn(label: Text('Agente')),
                      DataColumn(label: Text('Agente de cobertura')),
                    ],
                    rows:
                        scheduleList // Loops through dataColumnText, each iteration assigning the value to element
                            .map(
                              ((element) => DataRow(
                                    cells: <DataCell>[
                                      DataCell(Text(element![
                                          "ingreso"])), //Extracting from Map element the value
                                      DataCell(
                                          Text(element["sector_nombre"])),
                                      DataCell(Text(element["apellidos"] +
                                          " " +
                                          element["nombres"])),
                                     DataCell(Text(element["agente_cobertura_det"])),
                                    ],
                                  )),
                            )
                            .toList(),
                  ),
                ],
              ),
            ),
          )
        : pageLoadingView(),
  );
}

Widget pageLoadingView() {
  return Container(
    margin: EdgeInsets.only(top: 300),
    child: Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Visibility(
            visible: visible,
            child: Container(
                margin: EdgeInsets.only(bottom: 30),
                child: CircularProgressIndicator(
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.black),
                ))),
      ],
    ),
  );
}

Color hexToColor(String code) {
  return new Color(int.parse(code.substring(1, 7), radix: 16) + 0xFF000000);
}

解决方法

核心思路

DataTable本身不支持横向滚动,且默认列宽由内容决定,当列数/内容宽度超过屏幕时就会溢出。可以通过以下两种方式组合解决:

  1. 添加横向滚动:用SingleChildScrollView包裹DataTable,设置滚动方向为水平,让用户可以左右滑动查看全列。
  2. 内容自适应:给列标题和单元格内容包裹Expanded/Flexible,开启文本自动换行,让内容根据可用空间调整。

修改后的关键代码

替换原代码中的DataTable部分为以下内容:

// 新增横向滚动组件
SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: DataTable(
    columns: [
      DataColumn(label: Expanded(child: Text('Hora', softWrap: true))),
      DataColumn(label: Expanded(child: Text('Sector', softWrap: true))),
      DataColumn(label: Expanded(child: Text('Agente', softWrap: true))),
      DataColumn(label: Expanded(child: Text('Agente de cobertura', softWrap: true))),
    ],
    rows: scheduleList
        .map(((element) => DataRow(
              cells: <DataCell>[
                DataCell(Expanded(child: Text(element!["ingreso"], softWrap: true))),
                DataCell(Expanded(child: Text(element["sector_nombre"], softWrap: true))),
                DataCell(Expanded(child: Text(element["apellidos"] + " " + element["nombres"], softWrap: true))),
                DataCell(Expanded(child: Text(element["agente_cobertura_det"], softWrap: true))),
              ],
            )))
        .toList(),
  ),
)

如果需要按比例分配列宽,可以改用Flexible并设置flex属性:

DataColumn(label: Flexible(flex: 1, child: Text('Hora', softWrap: true))),
DataColumn(label: Flexible(flex: 2, child: Text('Sector', softWrap: true))),
// flex值越大,列宽度占比越高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:15:38