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被固定高度的SizedBox包裹限制了垂直空间,父级ListView禁用了滚动能力,同时窗口缩小时表格宽度超过可用空间无法自适应,最终导致溢出且无法联动滚动。
具体修改步骤
- 移除包裹
PaginatedDataTable的固定高度SizedBox,释放垂直空间限制 - 用
SingleChildScrollView包裹表格,开启水平滚动以适配窗口缩小场景 - 恢复父级
ListView的滚动物理属性,确保整体区域可滚动 - 修正重复嵌套的
MaterialApp,避免上下文冲突 - 调整
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
相关产品推荐
相关产品推荐

