Home > Net >  Flutter - Scrollable DataTable
Flutter - Scrollable DataTable

Time:06-19

I have a DataTable with a SingleChildScrollView and it works fine. I can scroll it horizontally, works perfect.

My question is; assume that I want to keep the ID column fixed, and I want to scroll horizontally only the other columns. How can I do this?

Here my code works fully horizontal:

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: Text('DataTable Demo'),
        ),
        body: ListView(
          children: [
            _createDataTable()
          ],
        ),
      ),
    );
  }
DataTable _createDataTable() {
    return DataTable(columns: _createColumns(), rows: _createRows());
  }
List<DataColumn> _createColumns() {
    return [
      DataColumn(label: Text('ID')),
      DataColumn(label: Text('Book')),
      DataColumn(label: Text('Author')),
      DataColumn(label: Text('Category')),
      DataColumn(label: Text('Category')),
      DataColumn(label: Text('Category'))
    ];
  }
List<DataRow> _createRows() {
    return _books
        .map((book) => DataRow(cells: [
              DataCell(Text('#'   book['id'].toString())),
              DataCell(Text(book['title'])),
              DataCell(Text(book['author'])),
              DataCell(FlutterLogo()),
              DataCell(FlutterLogo()),
              DataCell(FlutterLogo())
            ]))
        .toList();
  }
}

CodePudding user response:

For this, you have to use horizontal_data_table: ^4.1.1 plugin

https://pub.dev/packages/horizontal_data_table/install

CodePudding user response:

I'm not sure where you are stuck, but you can simply create a Row widget. The widget of the Row should render your sticky column and the second widget should be an Expanded wrapping your SingleChildScrollView.

The implementation should look something like this:

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('DataTable Demo'),
        ),
        body: SingleChildScrollView(
          physics: const ClampingScrollPhysics(),
          child: _getTable(),
        ),
      ),
    );
  }

  Row _getTable() {
    final stickyCells = _books.map(
      (e) => {
        "id": e["id"],
      },
    );

    final rows = _books.map(
      (e) => {
        "title": e["title"],
        "author": e["author"],
      },
    );

    return Row(
      children: [
        StickyColumnWidget(
          cells: stickyCells,
        ),
        Expanded(
          child: SingleChildScrollView(
            physics: const ClampingScrollPhysics(),
            scrollDirection: Axis.horizontal,
            child: Column(
              children: [
                ...rows.map(
                  (r) => RowWidget(
                    row: r,
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

class StickyColumnWidget extends StatelessWidget {
  final Iterable<Map> cells;

  const StickyColumnWidget({
    Key? key,
    required this.cells,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //create a column widget with cells
  }
}

class RowWidget extends StatelessWidget {
  final Map row;

  const RowWidget({
    Key? key,
    required this.row,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //return your original datatable row
  }
}

Try out and see if it works out for you.

  • Related