1+ package media.uqab.fuzzyble.dbCreator
2+
3+ import androidx.compose.foundation.ExperimentalFoundationApi
4+ import androidx.compose.foundation.background
5+ import androidx.compose.foundation.gestures.detectDragGestures
6+ import androidx.compose.foundation.layout.Box
7+ import androidx.compose.foundation.layout.Column
8+ import androidx.compose.foundation.layout.padding
9+ import androidx.compose.foundation.lazy.grid.GridCells
10+ import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
11+ import androidx.compose.foundation.lazy.grid.items
12+ import androidx.compose.foundation.onClick
13+ import androidx.compose.material.Card
14+ import androidx.compose.material.MaterialTheme
15+ import androidx.compose.material.Text
16+ import androidx.compose.runtime.*
17+ import androidx.compose.ui.Modifier
18+ import androidx.compose.ui.graphics.graphicsLayer
19+ import androidx.compose.ui.input.pointer.pointerInput
20+ import androidx.compose.ui.layout.onGloballyPositioned
21+ import androidx.compose.ui.layout.positionInRoot
22+ import androidx.compose.ui.unit.dp
23+
24+ private data class Item (val id : Int , val text : String , val list : Int )
25+
26+ @Composable
27+ fun DragAndDropExample () {
28+ val list1 = remember { mutableStateListOf<Item >() }
29+ val list2 = remember { mutableStateListOf<Item >() }
30+
31+ LaunchedEffect (Unit ) {
32+ list1.addAll(generateItems(5 , 1 ))
33+ list2.addAll(generateItems(3 , 2 ))
34+ }
35+
36+ var beingDragged by remember { mutableStateOf<Item ?>(null ) }
37+ var draggedOffsetX by remember { mutableStateOf(0f ) }
38+ var draggedOffsetY by remember { mutableStateOf(0f ) }
39+
40+ fun onDragStart (item : Item , x : Float , y : Float ) {
41+ draggedOffsetX = x; draggedOffsetY = y
42+ beingDragged = item
43+ }
44+
45+ fun onDrag (x : Float , y : Float ) {
46+ draggedOffsetX = x; draggedOffsetY = y
47+ }
48+
49+ fun onDrop (item : Item , fromList : Int ) {
50+ draggedOffsetX = 0f ; draggedOffsetY = 0f ; beingDragged = null
51+
52+ when (fromList) {
53+ 1 -> {
54+ list1.remove(item)
55+ list2.add(item)
56+ }
57+ 2 -> {
58+ list2.remove(item)
59+ list1.add(item)
60+ }
61+ }
62+ }
63+
64+ Box {
65+ Column {
66+ LazyHorizontalGrid (
67+ modifier = Modifier
68+ .weight(1f )
69+ .padding(16 .dp),
70+ rows = GridCells .Adaptive (200 .dp)
71+ ) {
72+ items(items = list1) { item ->
73+ DraggableItem (
74+ item = item,
75+ onDragStart = { it, x, y -> onDragStart(it, x, y) },
76+ onDrag = { x, y -> onDrag(x, y) },
77+ onDrop = { onDrop(it, 1 ) }
78+ )
79+ }
80+ }
81+
82+ LazyHorizontalGrid (
83+ modifier = Modifier
84+ .weight(1f )
85+ .padding(16 .dp),
86+ rows = GridCells .Fixed (2 )
87+ ) {
88+ items(list2) { item ->
89+ DraggableItem (
90+ item = item,
91+ onDragStart = { it, x, y -> onDragStart(it, x, y) },
92+ onDrag = { x, y -> onDrag(x, y) },
93+ onDrop = { onDrop(it, 2 ) }
94+ )
95+ }
96+ }
97+ }
98+
99+ if (beingDragged != null ) {
100+ DraggingItem (
101+ beingDragged!! ,
102+ draggedOffsetX,
103+ draggedOffsetY,
104+ )
105+ }
106+ }
107+
108+ }
109+
110+ @OptIn(ExperimentalFoundationApi ::class )
111+ @Composable
112+ private fun DraggableItem (
113+ item : Item ,
114+ modifier : Modifier = Modifier ,
115+ onDragStart : (Item , Float , Float ) -> Unit ,
116+ onDrag : (Float , Float ) -> Unit ,
117+ onDrop : (Item ) -> Unit
118+ ) {
119+ var offsetX by remember { mutableStateOf(0f ) }
120+ var offsetY by remember { mutableStateOf(0f ) }
121+ var globalX by remember { mutableStateOf(0f ) }
122+ var globalY by remember { mutableStateOf(0f ) }
123+ var isDragging by remember { mutableStateOf(false ) }
124+
125+ Card (
126+ modifier = modifier.padding(4 .dp)
127+ .onGloballyPositioned { layoutCoordinates ->
128+ globalX = layoutCoordinates.positionInRoot().x
129+ globalY = layoutCoordinates.positionInRoot().y
130+ }
131+ .onClick {
132+ println (item)
133+ }
134+ .pointerInput(Unit ) {
135+ detectDragGestures(
136+ onDragEnd = {
137+ println (" onDragEnd" )
138+ isDragging = false
139+ offsetX = globalX
140+ offsetY = globalY
141+ onDrop(item)
142+ },
143+ onDragStart = {
144+ offsetX = globalX + it.x
145+ offsetY = globalY + it.y
146+ isDragging = true
147+ onDragStart(item, offsetX, offsetY)
148+ },
149+ onDrag = { _, dragAmount ->
150+ offsetX + = dragAmount.x
151+ offsetY + = dragAmount.y
152+ onDrag(offsetX, offsetY)
153+ }
154+ )
155+ },
156+ elevation = 4 .dp
157+ ) {
158+ Text (
159+ text = item.text,
160+ modifier = Modifier
161+ .background(MaterialTheme .colors.primary)
162+ .padding(16 .dp)
163+ )
164+ }
165+ }
166+
167+ @Composable
168+ private fun DraggingItem (
169+ item : Item ,
170+ offsetX : Float ,
171+ offsetY : Float ,
172+ ) {
173+ DraggableItem (
174+ item,
175+ modifier = Modifier .graphicsLayer(
176+ translationX = offsetX,
177+ translationY = offsetY,
178+ alpha = 0.5f
179+ ),
180+ onDrop = {},
181+ onDragStart = {_, _, _ -> },
182+ onDrag = { _, _ -> },
183+ )
184+ }
185+
186+ private fun generateItems (count : Int , forList : Int ): List <Item > {
187+ return List (count) { index ->
188+ Item (id = index, text = " Item $index " , list = forList)
189+ }
190+ }
0 commit comments