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

Flutter:如何实现固定ID列、其余列可水平滚动的DataTable

实现固定ID列的DataTable布局

要实现固定ID列、其余列水平滚动的效果,我们可以把布局拆成固定的ID列区域和可水平滚动的内容列区域两部分,通过Row组件将它们并排组合,内容列嵌套在SingleChildScrollView(设置滚动方向为水平)中来实现滚动效果。下面是具体的实现方案:

完整代码示例

import 'package:flutter/material.dart';

void main() { runApp(MyApp()); }

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Map> _books = [
    { 'id': 100, 'title': 'Flutter', 'author': 'David Micheal' },
    { 'id': 102, 'title': 'Git and GitHub', 'author': 'Mike Nick' },
    { 'id': 101, 'title': 'Android Basics', 'author': 'Dave John' },
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Fixed ID Column Demo'),
        ),
        body: Row(
          children: [
            // 固定的ID列区域
            _buildFixedIdColumn(),
            // 可滚动的内容列区域
            Expanded(
              child: SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: _buildScrollableContentColumns(),
              ),
            ),
          ],
        ),
      ),
    );
  }

  // 构建固定的ID列(包含表头和数据行)
  Widget _buildFixedIdColumn() {
    return Container(
      width: 80, // 固定ID列的宽度,可按需调整
      decoration: const BoxDecoration(
        border: Border(right: BorderSide(color: Colors.grey, width: 0.5)),
      ),
      child: Column(
        children: [
          // ID表头,和DataTable表头高度对齐
          Container(
            height: 56,
            alignment: Alignment.center,
            child: const Text('ID', style: TextStyle(fontWeight: FontWeight.bold)),
          ),
          // ID数据行列表
          Expanded(
            child: ListView.builder(
              itemCount: _books.length,
              itemBuilder: (context, index) {
                return Container(
                  height: 52, // 和DataTable行高对齐
                  alignment: Alignment.center,
                  child: Text('#${_books[index]['id']}'),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  // 构建可滚动的内容列(包含除ID外的所有列)
  DataTable _buildScrollableContentColumns() {
    return DataTable(
      columns: _createContentColumns(),
      rows: _createContentRows(),
    );
  }

  List<DataColumn> _createContentColumns() {
    return [
      const DataColumn(label: Text('Book')),
      const DataColumn(label: Text('Author')),
      const DataColumn(label: Text('Category')),
      const DataColumn(label: Text('Category')),
      const DataColumn(label: Text('Category'))
    ];
  }

  List<DataRow> _createContentRows() {
    return _books
        .map((book) => DataRow(cells: [
              DataCell(Text(book['title'])),
              DataCell(Text(book['author'])),
              const DataCell(FlutterLogo()),
              const DataCell(FlutterLogo()),
              const DataCell(FlutterLogo())
            ]))
        .toList();
  }
}

关键细节说明

  • 布局拆分逻辑:用Row将固定列和滚动列分离,固定列设置固定宽度,滚动列通过Expanded占满剩余屏幕空间,保证布局自适应。
  • 高度对齐处理:手动设置固定列的表头和行高,和DataTable的默认高度(表头56px、行52px)保持一致,避免出现上下错位的问题。
  • 视觉区分:给固定列右侧添加灰色边框,清晰区分固定区域和滚动区域,提升整体UI的可读性。
  • 滚动实现:将内容列嵌套在SingleChildScrollView中,并指定scrollDirection: Axis.horizontal,实现仅内容列水平滚动的效果。

如果需要适配不固定的行高(比如内容换行导致行高变化),可以通过GlobalKey获取DataTable的行高信息,动态同步到固定列的行高度,不过对于大多数常规场景,上面的方案已经足够实用啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 00:39:07