对于新添加的视图,如何接收正在进行的拖动的 DragEvents?
How can I receive DragEvents of an ongoing drag for newly added Views?
据我所知,View
s 只有在实施了 onDragEvent()
或设置了 OnDragListener
后才会收到 DragEvent
s startDrag()
(或 startDragAndDrop()
for API 24+)被调用。如果 return true
DragEvent.ACTION_DRAG_STARTED
.
他们将继续收到额外的拖动事件
但是,我正在寻找一种方法来接收 DragEvent
s after 拖动操作已经开始,因为 View
s 添加到布局在拖动操作期间。
为了说明原因,我的情况大致如下:
我有一个 ViewPager2
和 ListView
片段,其列表项可以被拖动。如果我将一个项目拖到另一个项目上,我将“输入”该项目,然后会显示一个新的 ListView
片段和新的子项目。这很好用。
但是,由于在开始拖动操作时这些新的子项目不存在,所以当我继续将项目拖到这些新项目上时,它们不会收到 DragEvent
s。
所以,基本上,我希望能够在一次连续的拖动操作中进入多个深度。
是否可以让新添加的 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 项现在响应额外的 DragEvent
s。
我有点担心这种方法可能会产生意想不到的副作用。如果我在进一步测试时遇到这样的影响,我会更新这个答案。但现在就可以了。
如果有人知道这个 确实 可能会产生意想不到的副作用 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);
}
除此之外,我还没有遇到任何明显的问题,所以它可能刚刚很好地解决了我的问题。
据我所知,View
s 只有在实施了 onDragEvent()
或设置了 OnDragListener
后才会收到 DragEvent
s startDrag()
(或 startDragAndDrop()
for API 24+)被调用。如果 return true
DragEvent.ACTION_DRAG_STARTED
.
但是,我正在寻找一种方法来接收 DragEvent
s after 拖动操作已经开始,因为 View
s 添加到布局在拖动操作期间。
为了说明原因,我的情况大致如下:
我有一个 ViewPager2
和 ListView
片段,其列表项可以被拖动。如果我将一个项目拖到另一个项目上,我将“输入”该项目,然后会显示一个新的 ListView
片段和新的子项目。这很好用。
但是,由于在开始拖动操作时这些新的子项目不存在,所以当我继续将项目拖到这些新项目上时,它们不会收到 DragEvent
s。
所以,基本上,我希望能够在一次连续的拖动操作中进入多个深度。
是否可以让新添加的 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 项现在响应额外的 DragEvent
s。
我有点担心这种方法可能会产生意想不到的副作用。如果我在进一步测试时遇到这样的影响,我会更新这个答案。但现在就可以了。
如果有人知道这个 确实 可能会产生意想不到的副作用 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);
}
除此之外,我还没有遇到任何明显的问题,所以它可能刚刚很好地解决了我的问题。