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

Flutter PaginatedDataTable浏览器缩放时溢出且不跟随父滚动问题

问题

我开发了一个嵌套在带Scrollbar的ListView中的页面,页面主体由侧边导航栏(SideNavigationBar)和内容区组成,内容区使用PaginatedDataTable组件。当缩放浏览器窗口时,父组件可正常滚动,但PaginatedDataTable始终出现溢出错误,且无法跟随父组件滚动。请问如何调整代码布局,将PaginatedDataTable纳入父组件的滚动区域?

相关代码示例

import 'package:edar_app/cubit/auth/auth_cubit.dart';
import 'package:edar_app/locator.dart';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:side_navigation/side_navigation.dart';

void main() {
  setupLocator();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // scrollBehavior: MyCustomScrollBehavior(),
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),

      home: BlocProvider(
        create: (context) => AuthCubit(),
        child: HomePageScroll(),
      ),
    );
  }
}

class HomePageScroll extends StatefulWidget {
  HomePageScroll();

  @override
  _HomePageScrollState createState() => _HomePageScrollState();
}

class _HomePageScrollState extends State<HomePageScroll> {
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    List<DataColumn> dataColumns = [
      DataColumn(label: Text("Col 1")),
      DataColumn(label: Text("Col 2")),
    ];
    var dataTable = PaginatedDataTable(
      columns: dataColumns,
      source: DataSource(),
      showCheckboxColumn: false,
      dataRowHeight: 40,
      columnSpacing: 40,
      horizontalMargin: 10,
      rowsPerPage: 10,
      showFirstLastButtons: true,
    );

    List<SideNavigationBarItem> menuList = [
      SideNavigationBarItem(icon: Icons.home, label: "Home"),
    ];

    List content = [
      SizedBox(
        height: MediaQuery.of(context).size.height,
        child: dataTable,
      )
    ];
    return MaterialApp(
      home: Scaffold(
        body: Scrollbar(
          child: ListView(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            children: [
              ConstrainedBox(
                constraints: BoxConstraints(
                  maxWidth: MediaQuery.of(context).size.width,
                  maxHeight: MediaQuery.of(context).size.height,
                ),
                child: Row(
                  children: [
                    SideNavigationBar(
                      theme: SideNavigationBarTheme(
                        backgroundColor: Colors.white,
                        togglerTheme: SideNavigationBarTogglerTheme.standard(),
                        itemTheme: SideNavigationBarItemTheme(
                          unselectedItemColor: Colors.grey[900],
                        ),
                        dividerTheme: SideNavigationBarDividerTheme.standard(),
                      ),
                      selectedIndex: selectedIndex,
                      items: menuList,
                      toggler: SideBarToggler(
                          expandIcon: Icons.keyboard_arrow_right,
                          shrinkIcon: Icons.keyboard_arrow_left,
                          onToggle: () {
                            print('Toggle');
                          }),
                      onTap: (int value) {},
                    ),
                    Expanded(
                      child: content[selectedIndex],
                    )
                  ],
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

class DataSource extends DataTableSource {
  @override
  DataRow? getRow(int index) {
    return DataRow.byIndex(cells: [
      DataCell(Text("text 1")),
      DataCell(Text("text 2")),
    ]);
  }

  @override
  bool get isRowCountApproximate => false;

  @override
  int get rowCount => 2;

  @override
  int get selectedRowCount => 0;
}

状态截图

缩放前PaginatedDataTable状态

缩放前PaginatedDataTable状态

缩放后PaginatedDataTable状态

缩放后PaginatedDataTable状态

解决方案

问题根源在于:PaginatedDataTable被固定高度的SizedBox包裹限制了垂直空间,父级ListView禁用了滚动能力,同时窗口缩小时表格宽度超过可用空间无法自适应,最终导致溢出且无法联动滚动。

具体修改步骤

  1. 移除包裹PaginatedDataTable的固定高度SizedBox,释放垂直空间限制
  2. 用SingleChildScrollView包裹表格,开启水平滚动以适配窗口缩小场景
  3. 恢复父级ListView的滚动物理属性,确保整体区域可滚动
  4. 修正重复嵌套的MaterialApp,避免上下文冲突
  5. 调整ConstrainedBox的高度约束为minHeight,确保内容区至少占满屏幕

修改后的完整代码

import 'package:edar_app/cubit/auth/auth_cubit.dart';
import 'package:edar_app/locator.dart';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:side_navigation/side_navigation.dart';

void main() {
  setupLocator();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: BlocProvider(
        create: (context) => AuthCubit(),
        child: HomePageScroll(),
      ),
    );
  }
}

class HomePageScroll extends StatefulWidget {
  HomePageScroll();

  @override
  _HomePageScrollState createState() => _HomePageScrollState();
}

class _HomePageScrollState extends State<HomePageScroll> {
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    List<DataColumn> dataColumns = [
      DataColumn(label: Text("Col 1")),
      DataColumn(label: Text("Col 2")),
    ];
    var dataTable = PaginatedDataTable(
      columns: dataColumns,
      source: DataSource(),
      showCheckboxColumn: false,
      dataRowHeight: 40,
      columnSpacing: 40,
      horizontalMargin: 10,
      rowsPerPage: 10,
      showFirstLastButtons: true,
    );

    List<SideNavigationBarItem> menuList = [
      SideNavigationBarItem(icon: Icons.home, label: "Home"),
    ];

    List content = [
      // 用SingleChildScrollView包裹,支持水平滚动应对窗口缩小
      SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: dataTable,
      )
    ];
    return Scaffold(
      body: Scrollbar(
        child: ListView(
          shrinkWrap: true,
          // 恢复滚动能力,让整个页面联动滚动
          physics: const AlwaysScrollableScrollPhysics(),
          children: [
            ConstrainedBox(
              constraints: BoxConstraints(
                minHeight: MediaQuery.of(context).size.height,
              ),
              child: Row(
                children: [
                  SideNavigationBar(
                    theme: SideNavigationBarTheme(
                      backgroundColor: Colors.white,
                      togglerTheme: SideNavigationBarTogglerTheme.standard(),
                      itemTheme: SideNavigationBarItemTheme(
                        unselectedItemColor: Colors.grey[900],
                      ),
                      dividerTheme: SideNavigationBarDividerTheme.standard(),
                    ),
                    selectedIndex: selectedIndex,
                    items: menuList,
                    toggler: SideBarToggler(
                        expandIcon: Icons.keyboard_arrow_right,
                        shrinkIcon: Icons.keyboard_arrow_left,
                        onToggle: () {
                          print('Toggle');
                        }),
                    onTap: (int value) {},
                  ),
                  Expanded(
                    child: content[selectedIndex],
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

class DataSource extends DataTableSource {
  @override
  DataRow? getRow(int index) {
    return DataRow.byIndex(cells: [
      DataCell(Text("text 1")),
      DataCell(Text("text 2")),
    ]);
  }

  @override
  bool get isRowCountApproximate => false;

  @override
  int get rowCount => 2;

  @override
  int get selectedRowCount => 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:35:57