Drag and drop拖放框架

Drag and drop拖放框架

android11-release
应用使用 拖放 Drag and drop


Drag and drop拖放启动

APP调用启动

拖放 Drag and drop startDragAndDrop 启动
frameworks/base/core/java/android/view/View.java
在这里插入图片描述
frameworks\base\services\core\java\com\android\server\wm\Session.java
在这里插入图片描述

初始化DragState并注册InputChannel

  • 初始化DragState
  • 注册drag InputChannel\DragInputEventReceiver
  • 通知拖放开始mDragState.broadcastDragStartedLocked(touchX, touchY);触发DragEvent.ACTION_DRAG_STARTED

frameworks/base/services/core/java/com/android/server/wm/DragDropController.java
在这里插入图片描述
frameworks/base/services/core/java/com/android/server/wm/DragState.java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerInternal.java
frameworks/base/services/core/java/com/android/server/wm/DragInputEventReceiver.java
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

最后notifyLocationLocked

  • (touchedWin != mTargetWindow) && (mTargetWindow != null) 时触发 DragEvent.ACTION_DRAG_EXITED
  • touchedWin != null 时触发 DragEvent.ACTION_DRAG_LOCATION
    在这里插入图片描述
  • 通过ViewRootImplmpl层层调用,result = mView.dispatchDragEvent(event)通知APP并接受返回值
  • li.mOnDragListener.onDrag(this, event)真正通知APP
    frameworks/base/core/java/android/view/ViewRootImpl.java
    frameworks/base/core/java/android/view/View.java
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

Drag and drop拖放启动小结:

  1. APP启动startDragAndDrop,并View.OnDragListener监听
  2. 初始化DragState和注册drag InputChannel\DragInputEventReceiver
  3. ViewRootImpl中result = mView.dispatchDragEvent(event);发送到View,这里注意返回值result
  4. View中li.mOnDragListener.onDrag(this, event) 通知到APP监听
  5. SurfaceControl控制显示Surface,该显示与一般WMS显示不同
    Drag and drop拖放启动小结

Drag and drop拖放action触发问题

public static final int ACTION_DRAG_STARTED = 1;
public static final int ACTION_DRAG_LOCATION = 2;
public static final int ACTION_DROP = 3;
public static final int ACTION_DRAG_ENDED = 4;
public static final int ACTION_DRAG_ENTERED = 5;
public static final int ACTION_DRAG_EXITED = 6;

- ACTION_DRAG_STARTED

当应用调用 startDragAndDrop\startDrag 并获取拖动阴影后,视图对象的拖动事件监听器会立即收到此事件操作类型。
1 触发

上面也看到初始化registerInputChannel完成后mDragState.broadcastDragStartedLocked(touchX, touchY)通知完成:
performDrag -> broadcastDragStartedLocked -> sendDragStartedLocked -> newWin.mClient.dispatchDragEvent(event)\dispatchDragEvent(DragEvent event) -> handleDragEvent

2 通知APP监听前操作

frameworks/base/core/java/android/view/ViewRootImpl.java
handleDragEvent 中设置mCurrentDragView = nullmDragDescription保存 event.mClipDescription
在这里插入图片描述

3 result = mView.dispatchDragEvent(event)返回值

result 无论返回 truefalse 没有其他处理,所有没有其他影响。

- ACTION_DRAG_LOCATION

当收到 ACTION_DRAG_ENTERED 事件且拖动阴影仍在视图的边界框内时,该视图对象的拖动事件监听器会收到此事件操作类型。
1 触发

这里注册了drag InputChannel\DragInputEventReceiver,收到ACTION_MOVE事件调用mDragDropController.handleMotionEvent(Android 12 beta4这里没有任何操作),!mMuteInput最终调用到mDragState.notifyMoveLocked

frameworks/base/services/core/java/com/android/server/wm/DragInputEventReceiver.java
frameworks/base/services/core/java/com/android/server/wm/DragDropController.java
frameworks/base/services/core/java/com/android/server/wm/DragState.java
在这里插入图片描述在这里插入图片描述

在 DragState中notifyLocationLocked 通过touchedWin.mClient.dispatchDragEvent(evt)调用到ViewRootImpl中handleDragEvent

在这里插入图片描述
流程小结:drag InputChannel\DragInputEventReceiver -> handleMotionEvent -> notifyMoveLocked\notifyLocationLocked -> touchedWin.mClient.dispatchDragEvent(evt)\dispatchDragEvent(DragEvent event) -> handleDragEvent

2 通知APP监听前操作

frameworks/base/core/java/android/view/ViewRootImpl.java
在这里插入图片描述
在这里插入图片描述

3 result = mView.dispatchDragEvent(event)返回值

result 无论返回 truefalse!event.mEventHandlerWasCalled判断执行setDragFocus
在这里插入图片描述在这里插入图片描述

- ACTION_DROP

当用户将拖动阴影释放到视图对象上时,该视图对象的拖动事件监听器会收到此事件操作类型。仅当视图对象的监听器在响应 ACTION_DRAG_STARTED 拖动事件时返回布尔值 true 时,系统才会将该操作类型发送至该监听器。如果用户将拖动阴影释放到未注册监听器的视图上或不属于当前布局的任何视图上,系统都不会发送此操作类型。
如果成功处理了放下操作,监听器应返回布尔值 true。否则,它应返回 false。
1 触发

这里注册了drag InputChannel\DragInputEventReceiver,收到ACTION_UP\ACTION_CANCEL事件调用mDragDropController.handleMotionEvent(Android 12 beta4这里没有任何操作),!mMuteInput最终调用到mDragState.notifyDropLocked

在 DragState中notifyLocationLocked 通过touchedWin.mClient.dispatchDragEvent(evt)调用到ViewRootImpl中handleDragEvent

在这里插入图片描述
流程小结:drag InputChannel\DragInputEventReceiver -> handleMotionEvent -> notifyMoveLocked\notifyLocationLocked -> touchedWin.mClient.dispatchDragEvent(evt)\dispatchDragEvent(DragEvent event) -> handleDragEvent

ACTION_DRAG_LOCATION不同的是这里超时5s执行mDragState.endDragLocked()

在这里插入图片描述在这里插入图片描述

这里也可能不会触发DragEvent.ACTION_DROPcloseLocked()结束触发DragEvent.ACTION_DRAG_ENDED

在这里插入图片描述在这里插入图片描述

2 通知APP监听前操作

frameworks/base/core/java/android/view/ViewRootImpl.java
在这里插入图片描述
在这里插入图片描述

3 result = mView.dispatchDragEvent(event)返回true情况

APP返回true结束拖放closeLocked()结束触发DragEvent.ACTION_DRAG_ENDED
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

- ACTION_DRAG_ENDED

当系统结束拖动操作时,视图对象的拖动事件监听器会收到此事件操作类型。
此操作类型不一定在 ACTION_DROP 事件之后。
如果系统已发送 ACTION_DROP,收到 ACTION_DRAG_ENDED 操作类型并不表示放下操作成功。
监听器必须调用 getResult() 才能获得响应 ACTION_DROP 时所返回的值。
如果未发送 ACTION_DROP 事件,getResult() 将返回 false。
1 触发

读到这里,上面可看到closeLocked()方法触发DragEvent.ACTION_DRAG_ENDED
在这里插入图片描述
这里先注销drag input channel
在这里插入图片描述

2 通知APP监听前操作

在这里插入图片描述

3 result = mView.dispatchDragEvent(event)返回值

result 无论返回 truefalse都重置
在这里插入图片描述

- ACTION_DRAG_ENTERED\ACTION_DRAG_EXITED

**ACTION_DRAG_ENTERED**当拖动阴影刚进入视图的边界框时,视图对象的拖动事件监听器会收到此事件操作类型。这是监听器在拖动阴影进入边界框时收到的第一个事件操作类型。如果监听器想继续接收此操作的拖动事件,必须向系统返回布尔值 true。
**ACTION_DRAG_EXITED**当收到 ACTION_DRAG_ENTERED 和至少一个 ACTION_DRAG_LOCATION 事件,并且用户已将拖动阴影移至视图的边界框以外时,该视图对象的拖动事件监听器会收到此事件操作类型。
1 触发

从上面看到setDragFocus设置刷新时会触发
在这里插入图片描述

2 直接调用callDragEventHandler

ACTION_DRAG_ENTERED 说明返回 true,目前没有看到为什么
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xhBruce

佛系随缘,共同探讨

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值