조용한 담장

Flutter : DataTable 본문

Flutter

Flutter : DataTable

iosroid 2019. 11. 4. 11:24

DataTable

Material Design 의 데이터 테이블을 그려주는 Flutter Widget 이다.

 

DataTable class

DataTable({Key key, @required List columns, int sortColumnIndex, bool sortAscending: true, ValueSetter onSelectAll, double dataRowHeight: kMinInteractiveDimension, double headingRowHeight: 56.0, double horizontalMargin: 24.0, double columnSpacing: 56.0, @required List rows })

 

columns 리스트는 표의 첫 행에 들어가는 데이터 리스트 이며 각 열의 이름이 된다. 각 항목은 DataColumn 으로 구성되며 각각이 위젯이다.

rows 는 표의 각 행의 셀들에 들어갈 데이터를 가진 리스트이다. 각 항목은 DataRow 로 구성된다.

각 셀의 margin, space 값들을 지정하여 크기를 조절할 수 있다.

간단한 예제로는 아래와 같다.

DataTable(
columns: [
DataColumn(label: Text('A')),
DataColumn(label: Text('B')),
],
rows: [
DataRow(
cells: [
DataCell(Text('A1')),
DataCell(Text('B1')),
]
),
DataRow(
cells: [
DataCell(Text('A2')),
DataCell(Text('B2')),
]
),
],
)
view raw datatable1.dart hosted with ❤ by GitHub

DataColumn class

DataColumn({@required Widget label, String tooltip, bool numeric: false, DataColumnSortCallback onSort })

One column configuration must be provided for each column to display in the table.

표의 열에 관련된 설정을 가진 클래스 이다.

label 은 해당 열의 항목 이름이 된다.

numeric 은 해당 열의 데이터가 숫자로 처리되게 한다.

onSort 는 해당 열을 기준으로 정렬을 하는 콜백 함수이다.

DataRow class

DataRow({LocalKey key, bool selected: false, ValueChanged onSelectChanged, @required List cells })

One row configuration must be provided for each row to display in the table.

표의 행에 관한 설정을 가지며 각 셀의 데이터를 가지고 있는 클래스 이다.

cells 는 각 셀들의 값을 가진 위젯의 리스트 이다.

DataCell

DataCell(Widget child, { bool placeholder: false, bool showEditIcon: false, VoidCallback onTap })

The data for a cell of a DataTable.

표의 각 셀에 대항하는 위젯을 가진다. 설정에 따라 사용자가 값을 수정하거나 입력하도록 할 수 있다.

child 는 표의 셀에 그려지는 위젯이다.

Example

온라인 사이트에 공개되어 있는 CSV 파일을 읽어 DataTable 을 만드는 예제이다.

 

@override
void initState() {
super.initState();
_downloadCsv();
}
Future<void> _downloadCsv() async {
final url = "https://projects.fivethirtyeight.com/soccer-api/international/spi_global_rankings_intl.csv";
try {
var csvRead = await http.read(url);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DataTablePage(csvString: csvRead)),
);
} catch(e) {
print('download error:$e');
}
}
view raw datatable2.dart hosted with ❤ by GitHub

온라인에서 CSV 파일을 읽어온다.

 

List<String> csvRows;
List<String> csvHeadingRow;
@override
void initState() {
super.initState();
List<String> csvSplit = widget.csvString.split('\n');
csvHeadingRow = csvSplit[0].split(',');
csvSplit.removeAt(0);
csvRows = csvSplit;
}
view raw datatable3.dart hosted with ❤ by GitHub

첫번째 행은 아래의 값으로 되어 있는데 표에서 첫 줄에 들어가 각 열의 이름이 되는 값으로, 따로 csvHeadingRow 에 저장한다.

rank,name,confed,off,def,spi

그리고 첫 줄의 값을 뺀 나머지 표 데이터가 될 값들은 csvRows에 저장한다.

 

Widget _getDataTable() {
return DataTable(
horizontalMargin: 12.0,
columnSpacing: 28.0,
columns: _getColumns(),
rows: _getRows(),
);
}
view raw datatable4.dart hosted with ❤ by GitHub

표의 크기값을 지정하고, columnsrows 를 지정하는 함수를 호출한다.

 

List<DataColumn> _getColumns() {
List<DataColumn> dataColumn = [];
for (var i in csvHeadingRow) {
if (i == 'rank') {
dataColumn.add(DataColumn(label: Text(i), tooltip: i, numeric: true, onSort: _dataColumnSort));
} else {
dataColumn.add(DataColumn(label: Text(i), tooltip: i));
}
}
return dataColumn;
}
view raw datatable5.dart hosted with ❤ by GitHub

csvHeadingRow 의 값으로 columns 에 들어갈 List<DataColumn> 을 생성한다.

'rank' 열은 numeric 으로 설정하고 sort 함수 _dataColumnSort() 를 지정한다.

 

List<DataRow> _getRows() {
List<DataRow> dataRow = [];
for (var i=0; i<csvRows.length-1; i++) {
var csvDataCells = csvRows[i].split(',');
List<DataCell> cells = [];
for(var j=0; j<csvDataCells.length; j++) {
cells.add(DataCell(Text(csvDataCells[j])));
}
dataRow.add(DataRow(cells: cells));
}
return dataRow;
}
view raw datatable6.dart hosted with ❤ by GitHub

csvRows 의 값으로 rows 에 들어갈 List<DataRow> 를 생성한다.

 

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('DataTable Demo'),
),
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SingleChildScrollView(
child: _getDataTable(),
),
)
);
}
view raw datatable7.dart hosted with ❤ by GitHub

데이터가 많아 표가 크면 한 화면에 다 안그려진다. SingleChildScrollView 를 사용하여 화면이 스크롤 될 수 있게 해준다.

Example Code

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class WithNavigator extends StatefulWidget {
WithNavigator({Key key}) : super(key: key);
@override
_WithNavigatorState createState() => _WithNavigatorState();
}
class _WithNavigatorState extends State<WithNavigator> {
@override
void initState() {
super.initState();
_downloadCsv();
}
Future<void> _downloadCsv() async {
final url = "https://projects.fivethirtyeight.com/soccer-api/international/spi_global_rankings_intl.csv";
try {
var csvRead = await http.read(url);
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DataTablePage(csvString: csvRead)),
);
} catch(e) {
print('download error:$e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('DataTable Demo'),
),
body: Center(
child: Text('loading...', style: TextStyle(fontSize: 50.0),),
)
);
}
}
class DataTablePage extends StatefulWidget {
final csvString;
DataTablePage({Key key, @required this.csvString }) : super(key: key);
@override
_DataTablePageState createState() => _DataTablePageState();
}
class _DataTablePageState extends State<DataTablePage> {
List<String> csvRows;
List<String> csvHeadingRow;
@override
void initState() {
super.initState();
List<String> csvSplit = widget.csvString.split('\n');
csvHeadingRow = csvSplit[0].split(',');
csvSplit.removeAt(0);
csvRows = csvSplit;
}
void _dataColumnSort(int columnIndex, bool ascending) {
print('_dataColumnSort() $columnIndex, $ascending');
}
List<DataColumn> _getColumns() {
List<DataColumn> dataColumn = [];
for (var i in csvHeadingRow) {
if (i == 'rank') {
dataColumn.add(DataColumn(label: Text(i), tooltip: i, numeric: true, onSort: _dataColumnSort));
} else {
dataColumn.add(DataColumn(label: Text(i), tooltip: i));
}
}
return dataColumn;
}
List<DataRow> _getRows() {
List<DataRow> dataRow = [];
for (var i=0; i<csvRows.length-1; i++) {
var csvDataCells = csvRows[i].split(',');
List<DataCell> cells = [];
for(var j=0; j<csvDataCells.length; j++) {
cells.add(DataCell(Text(csvDataCells[j])));
}
dataRow.add(DataRow(cells: cells));
}
return dataRow;
}
Widget _getDataTable() {
return DataTable(
horizontalMargin: 12.0,
columnSpacing: 28.0,
columns: _getColumns(),
rows: _getRows(),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('DataTable Demo'),
),
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SingleChildScrollView(
child: _getDataTable(),
),
)
);
}
}

 

Reference

Flutter Documentation

Youtube Flutter Channel

'Flutter' 카테고리의 다른 글

Flutter : sqflite package (SQLite plugin)  (1) 2019.11.08
Flutter : permission_handler  (0) 2019.11.05
Flutter : Draggable  (0) 2019.10.28
Flutter : SelectableText  (0) 2019.10.21
Flutter : Navigator  (0) 2019.10.17
Comments