Flutter WebアプリでDataTabelを横スクロールさせる
FlutterのWebアプリ内で、csvファイルを読み込んで表示させる必要があったのですが、データが大きい時にスクロールをさせたいと思い調べてみました。
通常の縦スクロールはSingleChildScrollViewもしくはListViewを使えば問題なくできます。
横スクロールは、SingleChildScrollViewのscrollDirectionに、Axis.horizontalを指定すれば良いとありました。
SingleChildScrollView( // これは縦スクロール
children: [
SingleChildScrollView( // <- これは横スクロール
scrollDirection: Axis.horizontal, // 方向を指定
child: DataTable(columns: columnList, rows: rowList),
)
],
)
しかし、この方法では、どうしても横スクロールができません。
悩んでいましたところ、以下のサイトに原因と解決策がありました。
モバイル開発ではドラッグでスクロールできますが、WEB開発のデフォルトではドラッグでスクロールすることはできません。
https://note.com/hatchoutschool/n/nfe12a0aa069a
この最初の一文はちょっと衝撃的でした。まだまだ勉強不足です。
こちらのサイトを参考に、csvファイルを読み込み画面に表示するコードを書いてみました。
縦横方向ともに、スクロールできるかと思います。
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'dart:async' show Future;
import 'package:universal_html/html.dart' as html;
import 'dart:ui';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'CSV to Table',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<List<dynamic>> data = [];
Future<void> loadCSV() async {
final html.InputElement? uploadInput =
html.FileUploadInputElement() as html.InputElement?;
uploadInput!.click();
uploadInput.onChange.listen((e) {
final html.File file = uploadInput.files!.first!;
final html.FileReader reader = html.FileReader();
reader.readAsText(file);
reader.onLoadEnd.listen((e) {
final csvData = reader.result as String;
final List<List<dynamic>> csvTable =
CsvToListConverter().convert(csvData);
setState(() {
data = csvTable;
});
});
});
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('CSV to Table'),
),
body: SizedBox(
width: double.infinity,
child: data.isNotEmpty
? ScrollConfiguration( // <-- これでくくる
behavior: CustomScrollBehavior(),
child: SingleChildScrollView(
scrollDirection: Axis.vertical, // 縦スクロール
child: SingleChildScrollView(
scrollDirection: Axis.horizontal, //横スクロール
child: DataTable(
columns: data[0]
.map<DataColumn>((column) =>
DataColumn(label: Text(column.toString())))
.toList(),
rows: data
.skip(1)
.map<DataRow>((row) => DataRow(
cells: row
.map<DataCell>((cell) =>
DataCell(Text(cell.toString())))
.toList(),
))
.toList(),
))))
: const Center(
child: Text('No data available.'),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
loadCSV();
},
child: Icon(Icons.file_upload),
),
);
}
}
// 以下のクラスを追加
class CustomScrollBehavior extends MaterialScrollBehavior {
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}