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

如何基于Flutter Two Dimensional Scrollable包实现表格可展开行?

Flutter Two Dimensional Scrollable 可展开行实现方案

Flutter Two Dimensional Scrollable 包没有原生提供可展开行的实现,它的核心定位是提供二维滚动的基础能力,这类交互逻辑需要开发者基于现有组件自行实现。

你之前固定行高的方案确实不够灵活,这里提供一种更优雅的实现思路:

  • 用状态管理跟踪每行的展开状态(比如用StatefulWidget维护一个记录行展开状态的Map)
  • 在rowBuilder中根据当前行的展开状态,动态构建行内容:未展开时只渲染主内容,展开时将主内容和额外内容用Column组合,让行高自动适配内容,无需手动固定高度

示例代码如下:

class ExpandableTableExample extends StatefulWidget {
  @override
  State<ExpandableTableExample> createState() => _ExpandableTableExampleState();
}

class _ExpandableTableExampleState extends State<ExpandableTableExample> {
  final Map<int, bool> _expandedState = {};

  void _toggleRowExpand(int rowIndex) {
    setState(() {
      _expandedState[rowIndex] = !(_expandedState[rowIndex] ?? false);
    });
  }

  @override
  Widget build(BuildContext context) {
    return TableView.builder(
      columnCount: 3,
      rowCount: 8,
      rowBuilder: (context, rowIndex) {
        final isExpanded = _expandedState[rowIndex] ?? false;
        return GestureDetector(
          onTap: () => _toggleRowExpand(rowIndex),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // 主行内容
              Container(
                padding: EdgeInsets.symmetric(vertical: 12, horizontal: 8),
                decoration: BoxDecoration(
                  border: Border(bottom: BorderSide(color: Colors.grey.shade200)),
                ),
                child: Row(
                  children: [
                    Expanded(child: Text('行$rowIndex - 列1')),
                    Expanded(child: Text('行$rowIndex - 列2')),
                    Expanded(child: Text('行$rowIndex - 列3')),
                  ],
                ),
              ),
              // 展开区域:仅当展开时显示
              if (isExpanded)
                Container(
                  padding: EdgeInsets.symmetric(vertical: 16, horizontal: 8),
                  color: Colors.grey.shade50,
                  child: Row(
                    children: [
                      Expanded(child: Text('额外内容:行$rowIndex 详情1')),
                      Expanded(child: Text('额外内容:行$rowIndex 详情2')),
                      Expanded(child: Text('额外内容:行$rowIndex 详情3')),
                    ],
                  ),
                ),
            ],
          ),
        );
      },
      columnBuilder: (context, columnIndex) {
        return TableColumn(width: FixedTableColumnWidth(160));
      },
    );
  }
}

如果需要更流畅的过渡效果,可以给展开区域包裹AnimatedSize组件,搭配Curve实现平滑的高度变化:

if (isExpanded)
  AnimatedSize(
    duration: Duration(milliseconds: 300),
    curve: Curves.easeInOut,
    child: Container(/* 展开内容 */),
  ),

这种方案的优势在于行高完全由内容决定,不会出现固定行高导致的空间浪费或内容截断问题,交互逻辑也更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 18:23:29