Flutter多表格横向滚动、表头固定表体纵滚实现及异常排查
需求与问题
需要实现多表格横向滚动切换查看,每个表格表头固定、表体可纵向滚动,使用table_sticky_headers包开发后,控制台抛出No MediaQuery widget ancestor found异常,提示Scaffold需要MediaQuery祖先组件。
异常信息(翻译后)
构建Scaffold(dirty, state: ScaffoldState#d52a1(tickers: tracking 2 tickers))时抛出以下断言:
未找到MediaQuery widget祖先。
Scaffold widget需要MediaQuery widget祖先。
无法找到MediaQuery祖先的具体widget是:Scaffold
dirty
state: ScaffoldState#d52a1(tickers: tracking 2 tickers)
受影响widget的层级链为:"Scaffold ← MyApp ← [root]"
从传递给MediaQuery.of()的context开始,未找到任何MediaQuery祖先。这可能是因为你没有添加WidgetsApp、CupertinoApp或MaterialApp widget(这些widget会引入MediaQuery),也可能是因为你使用的context来自这些widget之上的widget。
引发错误的相关widget是:
Scaffold Scaffold:file:///D:/AndroidProjects/fixed_header_table/lib/main.dart:14:12
问题原因
代码中虽已使用MaterialApp,但异常层级链显示Scaffold直接处于MyApp与根组件之下,说明MaterialApp提供的MediaQuery上下文未正确传递到Scaffold环境中,导致table_sticky_headers组件内部调用MediaQuery.of()时找不到祖先。
解决方法与修正代码
核心调整
- 调整组件层级:将
MaterialApp移入MyApp内部,确保Scaffold完全处于MaterialApp子树中,保证MediaQuery上下文正常传递。 - 优化表格布局:为每个
StickyHeadersTable设置固定宽度,避免横向滚动时布局异常,同时保留表头固定、表体纵向滚动的特性。
修正后的完整代码
import 'package:flutter/material.dart'; import 'package:table_sticky_headers/table_sticky_headers.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Multiple Sticky Headers Tables', home: Scaffold( appBar: AppBar( title: const Text('Multiple Sticky Headers Tables'), ), body: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 固定表格宽度,保证横向滚动布局稳定 SizedBox( width: 400, child: StickyHeadersTable( columnsLength: 3, rowsLength: 5, columnsTitleBuilder: (i) => Container( padding: const EdgeInsets.all(8), color: Colors.blue[100], child: Text('Column $i'), ), rowsTitleBuilder: (i) => Container( padding: const EdgeInsets.all(8), color: Colors.blue[100], child: Text('Row $i'), ), contentCellBuilder: (i, j) => Container( padding: const EdgeInsets.all(8), color: Colors.white, child: Text('Table 1: Item $i-$j'), ), ), ), SizedBox( width: 500, child: StickyHeadersTable( columnsLength: 4, rowsLength: 6, columnsTitleBuilder: (i) => Container( padding: const EdgeInsets.all(8), color: Colors.green[100], child: Text('Column $i'), ), rowsTitleBuilder: (i) => Container( padding: const EdgeInsets.all(8), color: Colors.green[100], child: Text('Row $i'), ), contentCellBuilder: (i, j) => Container( padding: const EdgeInsets.all(8), color: Colors.white, child: Text('Table 2: Item $i-$j'), ), ), ), SizedBox( width: 300, child: StickyHeadersTable( columnsLength: 2, rowsLength: 3, columnsTitleBuilder: (i) => Container( padding: const EdgeInsets.all(8), color: Colors.orange[100], child: Text('Column $i'), ), rowsTitleBuilder: (i) => Container( padding: const EdgeInsets.all(8), color: Colors.orange[100], child: Text('Row $i'), ), contentCellBuilder: (i, j) => Container( padding: const EdgeInsets.all(8), color: Colors.white, child: Text('Table 3: Item $i-$j'), ), ), ), ], ), ), ), ); } }
效果说明
- 修复了
MediaQuery异常问题,Scaffold能正常获取上下文。 - 多表格支持横向滚动切换,每个表格的表头(横向、纵向)固定,表体内容可纵向滚动。
- 添加了内边距和背景色,提升表格的视觉可读性。
内容的提问来源于stack exchange,提问作者Istiaque Ahmed

