Home > database >  How can I receive DragEvents of an ongoing drag for newly added Views?
How can I receive DragEvents of an ongoing drag for newly added Views?

Time:05-06

As far as I can tell, Views only receive DragEvents if they had implemented onDragEvent() or had set an OnDragListener before startDrag() (or startDragAndDrop() for API 24 ) is called. They will then continue to receive additional drag events if they return true for DragEvent.ACTION_DRAG_STARTED.

However, I am looking for a way to receive DragEvents after a drag operation had already started, for Views that got added to the layout during the drag operation.


To illustrate why, my situation is roughly the following:

I have a ViewPager2 with ListView fragments whose list items can be dragged. If I drag an item over another item, I "enter" that item and a new ListView fragment is shown with new child items. This works fine.

However, since these new child items didn't exists at the time of starting the drag operation, they don't receive DragEvents when I continue to drag the item over those new items.

So, basically, I want to be able to enter multiple levels deep in one continuous drag operation.


Is it possible to have newly added Views receive DragEvents for an ongoing drag operation?

CodePudding user response:

Okay, I've managed to solve it by re-dispatching the original DragEvent (the one with action DragEvent.ACTION_DRAG_STARTED) to my main component, which is an instance of ViewGroup.

On inspecting the source code for ViewGroup.dispatchDragEvent() I found that ViewGroup has a member variable called mChildrenInterestedInDrag that gets filled with children interested in drag events, when DragEvent.ACTION_DRAG_STARTED is received.

So when I called ViewGroup.dispatchDragEvent() with the original DragEvent, after I entered an item in the list to view its child items, those new ListView child items were now responding to additional DragEvents.

I'm a bit worried that this approach might yield unexpected side effects. If I come across such effects upon further testing, I'll update this answer. But for now it will do.

If somebody knows that this indeed might yield unexpected side effects and/or has a better solution I'd love to hear them.


Addendum:

Upon storing the original DragEvent for re-dispatching, I had to "clone" the event, because, while it worked properly in an API 19 emulator, on an API 19 phone the original DragEvent's action were continuously altered during dragging, so its action wouldn't reflect DragEvent.ACTION_DRAG_STARTED anymore and re-dispatching didn't have the desired effect of registering newly added Views as interested in the ongoing drag operation.

Since DragEvents cannot be cloned or constructed, I had to "clone" it with the help of a Parcel:

void storeStartEvent(DragEvent startEvent) {
  Parcel parcel = Parcel.obtain();
  startEvent.writeToParcel(parcel, 0);
  // important to "rewind" the Parcel first
  parcel.setDataPosition(0);
  this.startEvent = DragEvent.CREATOR.createFromParcel(parcel);
}

Other than that, I didn't experience any noticeable problems yet, so it may have just solved my issue nicely.

  • Related