본문 바로가기

Flutter & Dart

[Flutter]플러터 Datatable 사용하기

반응형

플러터의 DataTable은 테이블 형태로 데이터를 표시하는 위젯입니다. 이 위젯은 주로 데이터 관리나 표시가 필요한 애플리케이션에서 사용됩니다. 기본 사용법과 함께 응용하는 방법까지 단계별로 설명드리겠습니다.

 

1. 기본적인 DataTable 사용법

DataTable은 세 가지 주요 구성 요소로 이루어져 있습니다.

  • columns: 테이블의 열(헤더).
  • rows: 테이블의 행.
  • DataColumn과 DataRow: 각각 열과 행을 정의하는 데 사용됩니다.
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flutter DataTable Example')),
        body: Center(child: SimpleDataTable()),
      ),
    );
  }
}

class SimpleDataTable extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DataTable(
      columns: const [
        DataColumn(label: Text('ID')),
        DataColumn(label: Text('Name')),
        DataColumn(label: Text('Age')),
      ],
      rows: const [
        DataRow(cells: [
          DataCell(Text('1')),
          DataCell(Text('Alice')),
          DataCell(Text('24')),
        ]),
        DataRow(cells: [
          DataCell(Text('2')),
          DataCell(Text('Bob')),
          DataCell(Text('27')),
        ]),
        DataRow(cells: [
          DataCell(Text('3')),
          DataCell(Text('Charlie')),
          DataCell(Text('30')),
        ]),
      ],
    );
  }
}

 

결과:

IDNameAge

1 Alice 24
2 Bob 27
3 Charlie 30

 

2. 기능 추가 (응용 방법)

2.1. 데이터 정렬

DataColumn에 onSort 콜백을 추가하여 열을 정렬할 수 있습니다.

 

class SortableDataTable extends StatefulWidget {
  @override
  _SortableDataTableState createState() => _SortableDataTableState();
}

class _SortableDataTableState extends State<SortableDataTable> {
  bool _sortAscending = true;
  List<Map<String, dynamic>> _data = [
    {'id': 1, 'name': 'Alice', 'age': 24},
    {'id': 2, 'name': 'Bob', 'age': 27},
    {'id': 3, 'name': 'Charlie', 'age': 30},
  ];

  void _sortData(int columnIndex, bool ascending) {
    if (columnIndex == 0) {
      _data.sort((a, b) => ascending ? a['id'] - b['id'] : b['id'] - a['id']);
    } else if (columnIndex == 2) {
      _data.sort((a, b) => ascending ? a['age'] - b['age'] : b['age'] - a['age']);
    }
    setState(() {
      _sortAscending = ascending;
    });
  }

  @override
  Widget build(BuildContext context) {
    return DataTable(
      sortAscending: _sortAscending,
      sortColumnIndex: 0,
      columns: [
        DataColumn(
          label: Text('ID'),
          onSort: (index, ascending) => _sortData(index, ascending),
        ),
        DataColumn(label: Text('Name')),
        DataColumn(
          label: Text('Age'),
          onSort: (index, ascending) => _sortData(index, ascending),
        ),
      ],
      rows: _data.map((item) {
        return DataRow(cells: [
          DataCell(Text(item['id'].toString())),
          DataCell(Text(item['name'])),
          DataCell(Text(item['age'].toString())),
        ]);
      }).toList(),
    );
  }
}

 

결과:

  • ID나 Age 헤더를 클릭하면 데이터를 오름차순/내림차순으로 정렬합니다.

2.2. 선택 가능 행 추가

행을 선택할 수 있도록 selected와 onSelectChanged를 사용합니다.

class SelectableDataTable extends StatefulWidget {
  @override
  _SelectableDataTableState createState() => _SelectableDataTableState();
}

class _SelectableDataTableState extends State<SelectableDataTable> {
  List<Map<String, dynamic>> _data = [
    {'id': 1, 'name': 'Alice', 'age': 24, 'selected': false},
    {'id': 2, 'name': 'Bob', 'age': 27, 'selected': false},
    {'id': 3, 'name': 'Charlie', 'age': 30, 'selected': false},
  ];

  @override
  Widget build(BuildContext context) {
    return DataTable(
      columns: const [
        DataColumn(label: Text('ID')),
        DataColumn(label: Text('Name')),
        DataColumn(label: Text('Age')),
      ],
      rows: _data.map((item) {
        return DataRow(
          selected: item['selected'],
          onSelectChanged: (isSelected) {
            setState(() {
              item['selected'] = isSelected ?? false;
            });
          },
          cells: [
            DataCell(Text(item['id'].toString())),
            DataCell(Text(item['name'])),
            DataCell(Text(item['age'].toString())),
          ],
        );
      }).toList(),
    );
  }
}

 

결과:

  • 각 행을 선택하면 선택 상태가 반영됩니다.

2.3. 동적 데이터 추가 및 삭제

DataTable에 데이터를 동적으로 추가하거나 삭제하려면 상태 관리가 필요합니다.

class DynamicDataTable extends StatefulWidget {
  @override
  _DynamicDataTableState createState() => _DynamicDataTableState();
}

class _DynamicDataTableState extends State<DynamicDataTable> {
  List<Map<String, dynamic>> _data = [
    {'id': 1, 'name': 'Alice', 'age': 24},
    {'id': 2, 'name': 'Bob', 'age': 27},
  ];

  void _addRow() {
    setState(() {
      _data.add({'id': _data.length + 1, 'name': 'New User', 'age': 20});
    });
  }

  void _deleteRow(int index) {
    setState(() {
      _data.removeAt(index);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: _addRow,
          child: Text('Add Row'),
        ),
        Expanded(
          child: SingleChildScrollView(
            scrollDirection: Axis.vertical,
            child: DataTable(
              columns: const [
                DataColumn(label: Text('ID')),
                DataColumn(label: Text('Name')),
                DataColumn(label: Text('Age')),
                DataColumn(label: Text('Actions')),
              ],
              rows: _data.asMap().entries.map((entry) {
                int index = entry.key;
                Map<String, dynamic> item = entry.value;
                return DataRow(cells: [
                  DataCell(Text(item['id'].toString())),
                  DataCell(Text(item['name'])),
                  DataCell(Text(item['age'].toString())),
                  DataCell(
                    IconButton(
                      icon: Icon(Icons.delete),
                      onPressed: () => _deleteRow(index),
                    ),
                  ),
                ]);
              }).toList(),
            ),
          ),
        ),
      ],
    );
  }
}

 

결과:

  • "Add Row" 버튼을 누르면 새 행이 추가됩니다.
  • 삭제 아이콘을 누르면 해당 행이 삭제됩니다.

. 응용 사례

  • 필터링 및 검색: TextField를 추가하여 테이블의 데이터를 필터링.
  • API 연동: 테이블 데이터를 서버와 연동하여 동적으로 로드 및 저장.
  • 반응형 테이블: SingleChildScrollView로 가로 및 세로 스크롤 지원.

DataTable은 기본적인 표 형식에서 시작해, 동적, 상호작용적 애플리케이션 개발까지 확장할 수 있는 유용한 도구입니다.

반응형