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
DragShadow
from getting back to its original position? What I want is just that when I release my drag, I just want theFrameLayout
to 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