はじめに
ドラッグ&ドロップを実装できるWidgetであるDraggableという存在を知って、面白そうだったので使ってみました。
コード
import 'package:flutter/material.dart';
class DraggablePage extends StatefulWidget {
const DraggablePage({super.key});
@override
State<DraggablePage> createState() => _DraggablePageState();
}
class _DraggablePageState extends State<DraggablePage> {
/// ドラッグしたデータのリスト
final List<int> draggedDataList = [];
/// ドラッグ対象のデータのリスト
final List<int> sourceDataList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('title'),
),
body: SafeArea(
child: Center(
child: Column(
children: [
Flexible(
// ドラッグ先
child: DragTarget<int>(
builder: (
context,
accepted,
rejected,
) {
return Container(
color: Colors.green,
height: 100,
child: ListView.separated(
itemCount: draggedDataList.length,
scrollDirection: Axis.horizontal,
separatorBuilder: (context, index) {
return const SizedBox(
width: 8,
);
},
itemBuilder: (context, index) {
return Container(
width: 80,
height: 80,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.amber,
),
child: Center(
child: Text("${draggedDataList[index]}")),
);
},
),
);
},
onAcceptWithDetails: (details) {
// ドラッグされた時のイベント
setState(() {
// ドラッグしたデータリストに追加
draggedDataList.add(details.data);
// ドラッグしたので、ドラッグ対象のデータから削除する
final index = sourceDataList
.indexWhere((element) => element == details.data);
sourceDataList.removeAt(index);
});
},
),
),
const Expanded(child: SizedBox()),
Flexible(
child: SizedBox(
height: 100,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Draggable(
data: sourceDataList[index],
// Drag中のWidget表示
feedback: _createCircle(
color: Colors.blueGrey,
),
// Drag中のDrag前のWidgetの表示
// (Drag中のchildの表示と同じ意味)
// Drag中は非表示にしたいので透明にする
childWhenDragging: _createCircle(
color: Colors.transparent,
),
// DragするWidget
child: _createCircle(
color: Colors.pink,
text: "${sourceDataList[index]}",
),
);
},
separatorBuilder: (context, index) {
return const SizedBox(
width: 8,
);
},
itemCount: sourceDataList.length,
),
),
),
],
),
),
),
);
}
Widget _createCircle({
required Color color,
String? text,
}) {
return Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
child: text == null
? null
: Center(
child: Text(text),
),
);
}
}