I am trying to make a reorderable GridLayout with drag and drop.
Basically, when I drag something in the GridLayout, it should reorder the GridLayout based on the dragging.
I have this GridLayout which has 6 FrameLayout inside.
<GridLayout
android:id="@+id/myGridLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="3">
<FrameLayout
android:background="@android:color/holo_blue_dark"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_columnWeight="1">
</FrameLayout>
<FrameLayout
android:background="@android:color/black"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_columnWeight="1">
</FrameLayout>
<FrameLayout
android:background="@android:color/darker_gray"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_columnWeight="1">
</FrameLayout>
<FrameLayout
android:background="@android:color/holo_green_dark"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_columnWeight="1">
</FrameLayout>
<FrameLayout
android:background="@android:color/holo_purple"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_columnWeight="1">
</FrameLayout>
<FrameLayout
android:background="@android:color/holo_red_dark"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_columnWeight="1">
</FrameLayout>
</GridLayout>
So It looks like the screenshot below
I have registered all the FrameLayouts in the GridLayout for LongClickListner and DragListener as per the codes below
for (i in 0 until myGridLayout.childCount) {
val childView = myGridLayout.getChildAt(i)
childView.setOnLongClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
it.visibility = View.INVISIBLE
it.startDragAndDrop(null, CustomDragShadowBuilder(it, lastTouch), it, 0)
} else it.startDrag(null, CustomDragShadowBuilder(it, lastTouch), it, 0)
true
}
childView.setOnDragListener { v, event ->
when (event.action) {
DragEvent.ACTION_DRAG_STARTED -> true
DragEvent.ACTION_DRAG_ENTERED -> {
val draggingView = event.localState as View
val dragEnteredIndex = myGridLayout.indexOfChild(v)
val draggingViewIndex = myGridLayout.indexOfChild(draggingView)
myGridLayout.removeViewAt(draggingViewIndex)
myGridLayout.addView(draggingView, dragEnteredIndex)
true
}
DragEvent.ACTION_DRAG_LOCATION -> true
DragEvent.ACTION_DRAG_EXITED -> true
DragEvent.ACTION_DROP -> true
DragEvent.ACTION_DRAG_ENDED -> {
val draggingView = event.localState as View
draggingView.post { run { draggingView.visibility = View.VISIBLE } }
true
}
else -> false
}
}
}
So, when you drag the red FrameLayout over to gray FrameLayout, the DragEvent.ACTION_DRAG_ENTERED is called. Then, I just remove the red FrameLayout and add it to the index of the gray FrameLayout where the DragShadow is over, so that I can reorder the GridLayout in real time. So, when I move around a FrameLayout in the GridLayout, I have got something like this, which is what I expect.
But, as you can see, when I release the drag, the red FrameLayout, or DragShadow goes back to its original position and console says I/ViewRootImpl[MainActivity]: Reporting drop result: false. Finally, the DragEvent.ACTION_DRAG_ENDED is called and make the red FrameLayout visible.
So, here are questions,
-
why the drag fails? Is this because I release the drag over the same
FrameLayout, which is red one please? -
Is there any way that I can prevent the
DragShadowfrom getting back to its original position? What I want is just that when I release my drag, I just want theFrameLayoutto appear at the new position, not getting back to its initial position.
Thank you guys in advance.
from Android drag and drop on the same view results in reporting drop result: false


No comments:
Post a Comment