对于新添加的视图,如何接收正在进行的拖动的 DragEvents?

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

据我所知,Views 只有在实施了 onDragEvent() 或设置了 OnDragListener 后才会收到 DragEvents startDrag()(或 startDragAndDrop() for API 24+)被调用。如果 return true DragEvent.ACTION_DRAG_STARTED.

他们将继续收到额外的拖动事件

但是,我正在寻找一种方法来接收 DragEvents after 拖动操作已经开始,因为 Views 添加到布局拖动操作期间。


为了说明原因,我的情况大致如下:

我有一个 ViewPager2ListView 片段,其列表项可以被拖动。如果我将一个项目拖到另一个项目上,我将“输入”该项目,然后会显示一个新的 ListView 片段和新的子项目。这很好用。

但是,由于在开始拖动操作时这些新的子项目不存在,所以当我继续将项目拖到这些新项目上时,它们不会收到 DragEvents。

所以,基本上,我希望能够在一次连续的拖动操作中进入多个深度。


是否可以让新添加的 View 接收 DragEvent 用于正在进行的拖动操作?

好的,我已经设法通过 re-dispatching 将原始 DragEvent(具有操作 DragEvent.ACTION_DRAG_STARTED 的那个)解决到我的主要组件,它是 [= 的一个实例13=].

在检查 ViewGroup.dispatchDragEvent() 的源代码时,我发现 ViewGroup 有一个名为 mChildrenInterestedInDrag 的成员变量,其中包含对拖动事件感兴趣的 children,当DragEvent.ACTION_DRAG_STARTED 收到。

所以当我用原来的 DragEvent 调用 ViewGroup.dispatchDragEvent() 时,在我在列表中输入一个项目以查看其 child 项目后,那些新的 ListView child 项现在响应额外的 DragEvents。

我有点担心这种方法可能会产生意想不到的副作用。如果我在进一步测试时遇到这样的影响,我会更新这个答案。但现在就可以了。

如果有人知道这个 确实 可能会产生意想不到的副作用 and/or 有更好的解决方案,我很想听听他们的意见。


附录:

在为 re-dispatching 存储原始 DragEvent 后,我不得不“克隆”该事件,因为虽然它在 API 19 模拟器中正常工作,但在 API 19 phone 原来的 DragEvent 的动作在拖动过程中不断改变,所以它的动作不会再反映 DragEvent.ACTION_DRAG_STARTED 而 re-dispatching 没有想要的将新添加的 View 注册为对正在进行的拖动操作感兴趣的效果。

由于无法克隆或构建 DragEvent,我不得不借助 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);
}

除此之外,我还没有遇到任何明显的问题,所以它可能刚刚很好地解决了我的问题。