【发布时间】:2019-11-18 09:44:10
【问题描述】:
我想创建一系列可以垂直滚动的表格,每个表格的行数/列数可能不同。
在每个表格中,我希望将最左边的列冻结在适当的位置,并且该表格中的其余列可以水平滚动,以防有许多列不适合屏幕的宽度。见截图:
我最初的计划是使用 ListView 进行表格之间的页面级垂直滚动,并且在每个表格中,有一个 Row of Columns,其中第一列是静态宽度,其余列包含在一个水平滚动 ListView。我从 Flutter 得到的错误并没有帮助我确定我需要做什么,但它显然与必须设置子 Widget 的边界有关。
错误:(通过使用固定高度容器包装水平 ListView 并收缩包装 ListView 修复了 7/9/19)
在 performResize() 期间抛出了以下断言: 水平视口被赋予了无限的宽度。 视口在滚动方向上扩展以填充其容器。在这种情况下,水平 视口被赋予了无限量的水平空间来扩展。这个情况 当一个可滚动的小部件嵌套在另一个可滚动的小部件中时,通常会发生这种情况。 如果此小部件始终嵌套在可滚动小部件中,则无需使用视口,因为 孩子们总会有足够的水平空间。在这种情况下,请考虑使用 Row 反而。否则,请考虑使用“shrinkWrap”属性(或 ShrinkWrappingViewport)来调整大小 视口的宽度与其子项的宽度之和。
新错误 7/9/19:
在布局期间抛出以下消息: 一个 RenderFlex 在右侧溢出了 74 个像素。 溢出的 RenderFlex 的方向为 Axis.horizontal。 溢出的 RenderFlex 边缘已在渲染中用黄色和 黑色条纹图案。这通常是由于内容对于 RenderFlex 来说太大了。 考虑应用弹性因子(例如,使用 Expanded 小部件)来强制 RenderFlex 以适应可用空间,而不是按其自然大小调整大小。 这被认为是一种错误情况,因为它表明存在不能被 见过。如果内容合法地大于可用空间,请考虑使用 在将 ClipRect 小部件放入 flex 之前,或者使用可滚动容器而不是 Flex, 像一个列表视图。 有问题的具体 RenderFlex 是:
RenderFlex#9bf67 relayoutBoundary=up5 溢出
创建者:行 ← RepaintBoundary-[] ← IndexedSemantics ←
NotificationListener ← KeepAlive ← AutomaticKeepAlive ← SliverList ←
SliverPadding ← 视口 ← IgnorePointer-[GlobalKey#74513] ← 语义 ← 监听器 ← ⋯
parentData:(可以使用大小)
约束:BoxConstraints(w=404.0, 0.0 尺寸:尺寸(404.0, 300.0)
方向:水平
mainAxisAlignment:开始
mainAxisSize: 最大值
crossAxisAlignment:居中
文本方向:ltr
这是我最初遇到的问题,然后才被报告的第一个问题搁置;我不明白为什么我的 ListView 没有创建可滚动容器。
代码:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
home: Scaffold(
appBar: AppBar(
title: Text('My App'),
backgroundColor: Colors.teal[400],
),
body: MyClass(),
),
);
}
}
const double headerCellWidth = 108.0;
const double cellPadding = 8.0;
const double focusedColumnWidth = 185.0;
const double rowHeight = 36.0;
class MyClass extends StatefulWidget {
@override
_MyClassState createState() => _MyClassState();
}
class _MyClassState extends State<MyClass> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return ListView(
padding: EdgeInsets.all(5.0),
children: <Widget>[
Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
color: Colors.grey,
padding: EdgeInsets.all(cellPadding),
width: headerCellWidth,
),
HeaderCell('ABC'),
HeaderCell('123'),
HeaderCell('XYZ'),
],
),
Container(
height: 300.0, // Could compute height with fixed rows and known number of rows in advance
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: <Widget>[
Column(
children: <Widget>[
Container(
color: Colors.grey[300],
padding: EdgeInsets.all(cellPadding),
height: rowHeight,
width: focusedColumnWidth,
),
NumberCell('89'),
NumberCell('92'),
NumberCell('91'),
NumberCell('90'),
NumberCell('91'),
NumberCell('89'),
],
),
Column(
children: <Widget>[
Container(
color: Colors.grey[300],
padding: EdgeInsets.all(cellPadding),
height: rowHeight,
width: focusedColumnWidth,
),
NumberCell('89'),
NumberCell('92'),
NumberCell('91'),
NumberCell('90'),
NumberCell('91'),
NumberCell('89'),
],
),
],
),
),
],
),
],
);
}
}
class HeaderCell extends StatelessWidget {
HeaderCell(this.text);
final String text;
@override
Widget build(BuildContext context) {
return Container(
height: rowHeight,
padding: EdgeInsets.all(cellPadding),
width: headerCellWidth,
child: Text(
text,
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
);
}
}
class NumberCell extends StatelessWidget {
NumberCell(this.text);
final String text;
@override
Widget build(BuildContext context) {
return Container(
height: rowHeight,
width: focusedColumnWidth,
padding: EdgeInsets.all(cellPadding),
child: Text(
text,
),
);
}
}
【问题讨论】:
-
随着时间的推移,嵌套的行和列会变得混乱且难以阅读。您是否尝试过使用 Table 类:api.flutter.dev/flutter/widgets/Table-class.html
-
我将看看使用表格而不是嵌套的行/列;最初我关闭了一个表格,因为它不是用于滚动的,而且我必须支持 3 个列宽,并且只有部分表格是可滚动的(如上面的屏幕截图所示,最左边的列被锁定)。