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

Flutter带固定表头滚动表格消除ParentDataWidget异常

解决Flutter固定表头滚动表格的"Incorrect use of ParentDataWidget"异常

问题原因分析

出现该异常的核心是ParentDataWidget(此处为Flexible)被放置在了错误的父组件中,具体问题点:

  • SingleChildScrollView的直接子节点是Flexible,但Flexible仅能作为Row/Column等Flex组件的子节点使用,不能直接嵌套在SingleChildScrollView下。
  • 内层重复嵌套Scaffold,外层已存在Scaffold,重复嵌套会导致布局上下文冲突。
  • SizedBox设置height: screenHeight,结合外层Expanded会触发布局溢出,引发额外错误。
  • 手动创建24个数据变量,代码冗余且易出错。

修复后的优化代码

// ignore_for_file: camel_case_types, prefer_interpolation_to_compose_strings

import 'package:bps_cilacap/restAPI/repository_penduduk_kecamatan.dart';
import 'package:flutter/material.dart';
import 'package:bps_cilacap/format_angka.dart';

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

  @override
  State<JumlahPendudukKecamatanA> createState() =>
      _JumlahPendudukKecamatanAState();
}

RepositoryJumlahPendudukKecamatan jumlahPendudukKecamatan =
    RepositoryJumlahPendudukKecamatan();

class _JumlahPendudukKecamatanAState extends State<JumlahPendudukKecamatanA> {
  @override
  Widget build(BuildContext context) {
    final screenHeight = MediaQuery.of(context).size.height -
        MediaQuery.of(context).padding.top -
        MediaQuery.of(context).padding.bottom;
    final screenWidth = MediaQuery.of(context).size.width -
        MediaQuery.of(context).padding.left -
        MediaQuery.of(context).padding.right;

    return Scaffold(
      body: FutureBuilder(
        future: jumlahPendudukKecamatan.getData(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            List isipendudukkecamatan = snapshot.data as List;
            // 提取总计行(最后一条数据)
            final totalData = isipendudukkecamatan.last;
            // 提取前24条区县数据
            final kecamatanDataList = isipendudukkecamatan.take(24).toList();

            return Column(
              children: <Widget>[
                // 固定表头行
                Container(
                  height: screenHeight * 0.06,
                  child: Row(
                    children: [
                      Flexible(
                        fit: FlexFit.tight,
                        flex: 4,
                        child: Container(
                          color: Colors.green,
                          alignment: Alignment.center,
                          child: const Text(
                            "Kecamatan",
                            style: TextStyle(
                                color: Colors.white, fontWeight: FontWeight.bold),
                          ),
                        ),
                      ),
                      Flexible(
                        fit: FlexFit.tight,
                        flex: 2,
                        child: Container(
                          color: Colors.green,
                          alignment: Alignment.center,
                          child: const Text(
                            "Lk",
                            style: TextStyle(
                                color: Colors.white, fontWeight: FontWeight.bold),
                          ),
                        ),
                      ),
                      Flexible(
                        fit: FlexFit.tight,
                        flex: 2,
                        child: Container(
                          color: Colors.green,
                          alignment: Alignment.center,
                          child: const Text(
                            "Pr",
                            style: TextStyle(
                                color: Colors.white, fontWeight: FontWeight.bold),
                          ),
                        ),
                      ),
                      Flexible(
                        fit: FlexFit.tight,
                        flex: 2,
                        child: Container(
                          color: Colors.green,
                          alignment: Alignment.center,
                          child: const Text(
                            "Lk + Pr",
                            style: TextStyle(
                                color: Colors.white, fontWeight: FontWeight.bold),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                // 可滚动表格内容
                Expanded(
                  child: SingleChildScrollView(
                    child: SizedBox(
                      width: screenWidth,
                      child: Column(
                        children: [
                          // 循环生成24行区县数据
                          for (int i = 0; i < kecamatanDataList.length; i++)
                            _buildTableRow(
                              index: i + 1,
                              kecamatan: kecamatanDataList[i].kecamatan,
                              lk: int.parse(kecamatanDataList[i].lk1),
                              pr: int.parse(kecamatanDataList[i].pr1),
                              screenHeight: screenHeight,
                            ),
                          // 总计行
                          _buildTableRow(
                            index: -1, // 标记为总计行
                            kecamatan: totalData.kecamatan,
                            lk: int.parse(totalData.lk1),
                            pr: int.parse(totalData.pr1),
                            screenHeight: screenHeight,
                            isTotal: true,
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            );
          } else if (snapshot.hasError) {
            return const Center(child: Text('Database Error'));
          } else {
            return const Center(child: CircularProgressIndicator(strokeWidth: 3));
          }
        },
      ),
    );
  }

  // 封装表格行组件,复用代码
  Widget _buildTableRow({
    required int index,
    required String kecamatan,
    required int lk,
    required int pr,
    required double screenHeight,
    bool isTotal = false,
  }) {
    final textStyle = isTotal
        ? const TextStyle(fontWeight: FontWeight.bold, fontSize: 16)
        : const TextStyle(fontWeight: FontWeight.normal);
    final kecText = isTotal
        ? kecamatan
        : "${index.toString().padLeft(2, ' ')}. $kecamatan";

    return Container(
      height: screenHeight * 0.032,
      padding: const EdgeInsets.symmetric(horizontal: 2),
      child: Row(
        children: [
          Flexible(
            fit: FlexFit.tight,
            flex: 4,
            child: Align(
              alignment: Alignment.centerLeft,
              child: Text(
                kecText,
                style: textStyle,
              ),
            ),
          ),
          Flexible(
            fit: FlexFit.tight,
            flex: 2,
            child: Align(
              alignment: Alignment.centerRight,
              child: Text(
                Format.convertTo(lk, 0),
                style: textStyle,
              ),
            ),
          ),
          Flexible(
            fit: FlexFit.tight,
            flex: 2,
            child: Align(
              alignment: Alignment.centerRight,
              child: Text(
                Format.convertTo(pr, 0),
                style: textStyle,
              ),
            ),
          ),
          Flexible(
            fit: FlexFit.tight,
            flex: 2,
            child: Align(
              alignment: Alignment.centerRight,
              child: Text(
                Format.convertTo(lk + pr, 0),
                style: textStyle,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

关键优化点说明

  1. 移除错误嵌套的Flexible:删除SingleChildScrollView下的Flexible,SingleChildScrollView无需弹性布局子节点。
  2. 删除冗余Scaffold:外层已存在Scaffold,内层重复嵌套会导致布局上下文冲突,直接移除。
  3. 循环生成表格行:用for循环+封装的_buildTableRow组件替代手动创建24个变量,减少代码冗余,提升可维护性。
  4. 修复总数计算错误:将原代码中错误的lk1 + pr2修正为lk + pr,保证数据准确性。
  5. 优化布局结构:表头行固定高度,表格内容通过Expanded填充剩余空间,SingleChildScrollView仅负责垂直滚动,避免布局溢出。
  6. 移除无用PageView:原代码中PageView.builder的itemCount=1无实际意义,直接返回布局内容即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:15:07