LoginSignup
1
1

【Flutter】ドラッグ&ドロップを実装

Posted at

はじめに

ドラッグ&ドロップを実装できるWidgetであるDraggableという存在を知って、面白そうだったので使ってみました。

draggable2.gif

コード

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),
            ),
    );
  }
}

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1