当前位置: 首页 > 知识库问答 >
问题:

如何在Flutter中创建一个固定列的水平滚动表?

钱毅
2023-03-14

我想创建一系列可以垂直滚动的表,每个表的行/列数可能不同。

在每个表中,我希望将最左边的列冻结在适当的位置,并且该表中的其余列可以水平滚动,以防有许多列不适合屏幕的宽度。见截图:

我最初的计划是使用ListView在表之间进行页面级别的垂直滚动,在每个表中有一行列,其中第一列是静态宽度,其余的列包含在水平滚动的ListView中。我从Flutter得到的错误并不能帮助我确定我需要做什么,但它显然与必须设置子部件的边界有关。

新错误7/9/19:

在布局过程中抛出了以下消息:右侧的RenderFlex溢出了74个像素。溢出的RenderFlex的方向为Axis.Health。溢出的RenderFlex的边缘已在呈现中用黄色和黑色条纹图案标记。这通常是由于内容对于RenderFlex来说太大造成的。考虑应用flex因子(例如,使用扩展的小部件)来强制RenderFlex的子级适应可用空间,而不是调整到它们的自然大小。这被认为是错误条件,因为它指示存在看不到的内容。如果内容合法地大于可用空间,请考虑在将其放入flex之前使用ClipRect小部件对其进行裁剪,或者使用可滚动容器而不是flex,比如ListView。有问题的特定RenderFlex是:
RenderFlex#9bf67 relayoutboundary=Up5溢出
创建者:Row\repaintboundary=[<0>]\IndexedSemantics\
NotificationListener\KeepAlive\AutomaticKeepAlive\SliverList\
SliverPadding\Viewport\nignorrepointer-[globalkey#74513]\semanicsypenter\\
parentdata:(cable use size)
约束br>MainAxisSize:max
CrossAxisAlignment:Center
TextDirection: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,
      ),
    );
  }
}

共有1个答案

颜新
2023-03-14

下面是一个快速的例子,结果是:Video

List<Widget> _buildCells(int count) {
  return List.generate(
    count,
    (index) => Container(
      alignment: Alignment.center,
      width: 120.0,
      height: 60.0,
      color: Colors.white,
      margin: EdgeInsets.all(4.0),
      child: Text("${index + 1}", style: Theme.of(context).textTheme.title),
    ),
  );
}

List<Widget> _buildRows(int count) {
  return List.generate(
    count,
    (index) => Row(
      children: _buildCells(10),
    ),
  );
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(),
    body: SingleChildScrollView(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: _buildCells(20),
          ),
          Flexible(
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: _buildRows(20),
              ),
            ),
          )
        ],
      ),
    ),
  );
}
 类似资料:
  • 问题内容: 我目前正在尝试在用户在X轴上滚动时修复表格中的第一列。我正在使用此结构: 用户将选择项目的数量,即表中可能是90个项目。这将需要在X轴上滚动。我得到的问题是: 如何确定(和中的)标记的位置? 我一直在看其他一些线程,但是它们并没有真正解释我如何实现固定列,这使我很难理解代码的作用和应做的事情。 我还检查了人们将标题栏拆分到另一个表中的解决方案。这对我来说是不可能的,因为稍后我会将数据导

  • 问题内容: 我一直在尝试一种方法来制作具有固定的第一列的表(表的其余部分具有水平的溢出),我看到有类似问题的帖子。但是固定的列位似乎没有解决。帮帮我? 问题答案: 我有一个类似的样式,如下所示:

  • 问题内容: 如果将元素设置为,并且有一个垂直滚动条,则该元素的宽度将等于视口加上滚动条的宽度。 有可能防止这种情况吗? 是否可以在不禁用整个页面水平滚动的情况下防止这种情况?除了更改css / markup以使元素占主体宽度的100%之外,我什么都没想到。 已在Windows 8.1的Chrome版本43.0.2357.81 m和FF 36.0.1和Opera 20.0.1387.91中进行测试

  • 如果将元素设置为并且存在垂直滚动条,则元素的宽度将等于视口加上滚动条的宽度。 有没有可能防止这种情况发生? 有没有可能在不禁用整个页面的水平滚动的情况下防止这种情况发生?除了改变我的CSS/标记,使元素100%的身体宽度,我什么也想不出来。 在Windows 8.1上的Chrome版本43.0.2357.81m&FF 36.0.1和Opera 20.0.1387.91中进行了测试 下面是要求的代码

  • 我一直在努力解决HTML/CSS粘滞头+滚动条的问题。我们正在创建一个程序,一旦containersize达到某个点(取决于用户的分辨率),就需要滚动条显示出来。 我在表中的第二列上强制设置一个min-width,因此表在某个点停止递减,并强制容器保持在某个宽度。容器上的溢出显示水平滚动条。一切正常。一旦我为垂直滚动添加了第二个滚动条,事情就会变得一团糟。有人有解决这个问题的办法吗?我想在.tab

  • 问题内容: 我有一个,当行太多时,会出现滚动条,但是当行太长时,该行会分成两行,而不是出现水平滚动条,如何使水平条出现而不是分成两行,我的添加如下: 问题答案: 正如我们自己的Rob Camick 在这里介绍的那样,您可以尝试使用类似… 这将停止行/自动换行