以下部分介绍了拖放过程的一些关键概念。
拖放过程
拖放过程有四个步骤或状态:已开始、 继续、丢弃和结束
- 已开始
为响应用户的拖动手势,您的应用会调用
startDragAndDrop()
,用于指示系统开始执行拖放操作。通过 方法的参数提供以下内容:- 要拖动的数据。
- 用于绘制拖动阴影的回调
- 用于描述所拖动数据的元数据
- 系统通过回调应用进行响应以获取拖动 阴影。然后,系统会在设备上显示拖动阴影。
- 接下来,系统发送具有操作类型的拖动事件
ACTION_DRAG_STARTED
:拖动到拖动事件 当前布局中所有View
对象的监听器。接收者 继续接收拖拽事件,包括可能的放下 事件 - 拖动事件监听器必须返回true
。这会注册 监听器。只有已注册的监听器才能继续 用于接收拖动事件。此时,监听器也可更改 拖放目标View
对象的外观,表明该视图可以 接受丢弃事件。 - 如果拖动事件监听器返回
false
,则不会接收拖动事件 事件,直到系统发送拖动事件 操作类型为ACTION_DRAG_ENDED
。 通过返回false
,监听器会告知系统它不感兴趣 而不想接受拖动的数据。
- 正在继续
- 用户继续拖动。当拖动阴影与
边界框,则系统会发送一个或多个拖动事件
拖动事件监听器。监听器可能会改变
放置目标
View
以响应该事件。例如,如果事件 表示拖动阴影会进入拖放的边界框 target - 操作类型ACTION_DRAG_ENTERED
— 监听器可通过突出显示View
来做出反应。 - 已放下
- 用户在拖放的边界框内释放拖动阴影
目标。系统向放置目标的监听器发送包含操作的拖动事件
类型
ACTION_DROP
。 拖动事件对象包含在 对启动操作的startDragAndDrop()
的调用。监听器为 如果监听器成功,预期会返回布尔值true
给系统 处理丢弃的数据。 :仅当用户将拖动阴影放在View
的边界框,其监听器已注册接收拖动事件 (拖放目标)。如果用户在任何其他时间之后释放拖动阴影, 系统不会发送任何ACTION_DROP
拖动事件。 - 已结束
在用户释放拖动阴影且系统发送
触发操作类型为
ACTION_DROP
的拖动事件,如有必要, 会发送一个操作类型为ACTION_DRAG_ENDED
的拖动事件,以指明 拖放操作结束。无论用户身在何处 释放拖动阴影。该事件会发送到 注册以接收拖动事件,即使监听器也收到了ACTION_DROP
事件。
有关以上每个步骤的详细介绍,请参阅 拖放操作。
拖动事件
系统以 DragEvent
对象的形式发出拖动事件,
包含描述拖放操作中发生的情况的操作类型
过程。该对象还可能包含其他数据,具体取决于操作类型。
拖动事件监听器可接收 DragEvent
对象。为了获取操作类型,监听器会调用 DragEvent.getAction()
。有六个可能的值由 DragEvent
类中的常量定义,
如表 1 所述:
操作类型 | 含义 |
---|---|
ACTION_DRAG_STARTED |
应用调用 startDragAndDrop() 并获取
拖动阴影。如果监听器想要继续接收拖动事件
对于此操作,必须向true
系统。
|
ACTION_DRAG_ENTERED |
拖动阴影会进入拖动事件监听器的
View 。这是监听器的第一个事件操作类型
。
|
ACTION_DRAG_LOCATION |
在其后
ACTION_DRAG_ENTERED 事件,拖动阴影仍然是
在拖动事件监听器的
View 。
|
ACTION_DRAG_EXITED |
已关注“ACTION_DRAG_ENTERED ”和至少一个
ACTION_DRAG_LOCATION 事件,拖动阴影会移动
在拖动事件监听器的
View 。
|
ACTION_DROP |
拖动阴影会在拖动事件监听器的
View 。系统会将此操作类型发送到 View 。
仅当监听器返回布尔值时,才返回该对象的监听器
true 回复
ACTION_DRAG_STARTED 拖动事件。此操作类型
当用户将拖动阴影释放到 View 上时发送
其监听器未注册或用户松开拖动操作
覆盖不属于当前布局的任何内容。
如果监听器返回布尔值 |
ACTION_DRAG_ENDED |
系统即将结束拖放操作。此操作类型
并不一定在 ACTION_DROP 事件之后。如果
系统会发送 ACTION_DROP ,收到
ACTION_DRAG_ENDED 操作类型并不意味着
投放成功。监听器必须调用
getResult() ,
如表 2 所示,以获取
在响应 ACTION_DROP 时返回。如果
未发送 ACTION_DROP 事件,则
getResult() 会返回 false 。
|
DragEvent
对象还包含应用的数据和元数据
在 startDragAndDrop()
调用中向系统提供的内容。部分数据
仅对某些操作类型有效(如表 2 所述)。有关
事件及其相关数据的详细信息,请参阅
拖放操作。
getAction() 值 |
getClipDescription() 值 |
getLocalState() 值 |
getX() 值 |
getY() 值 |
getClipData() 值 |
getResult() 值 |
---|---|---|---|---|---|---|
ACTION_DRAG_STARTED |
✓ | ✓ | ||||
ACTION_DRAG_ENTERED |
✓ | ✓ | ||||
ACTION_DRAG_LOCATION |
✓ | ✓ | ✓ | ✓ | ||
ACTION_DRAG_EXITED |
✓ | ✓ | ||||
ACTION_DROP |
✓ | ✓ | ✓ | ✓ | ✓ | |
ACTION_DRAG_ENDED |
✓ | ✓ |
DragEvent
方法 getAction()
、
describeContents()
,
writeToParcel()
、
和toString()
始终
返回有效数据。
如果某个方法不包含特定操作类型的有效数据,它会返回
null
或 0,具体取决于其结果类型。
拖动阴影
在执行拖放操作期间,系统会显示一张图片,让用户 拖动。对于数据移动操作,此图片表示用户正在拖动的数据。对于其他操作,此图片表示拖动操作的某个方面。
此图片称为拖动阴影。您可以使用针对
一
View.DragShadowBuilder
对象。您在开始拖放时将构建器传递给系统
操作(使用 startDragAndDrop()
)。作为对
startDragAndDrop()
时,系统会调用您在
View.DragShadowBuilder
以获取拖动阴影。
View.DragShadowBuilder
类有两个构造函数:
View.DragShadowBuilder(View)
该构造函数可接受您的应用的任何
View
对象。该构造函数会将View
对象存储在View.DragShadowBuilder
对象中,以便回调可以获取视图对象来构造拖动阴影。视图不一定是 用户选择开始拖动操作的View
。如果您使用该构造函数,则无需扩展
View.DragShadowBuilder
,也无需替换其方法。默认情况下,系统会拖动 与作为实参传递的View
具有相同的外观的阴影, 且广告位于用户轻触屏幕的位置之下。View.DragShadowBuilder()
如果使用此构造函数,则
View
对象在View.DragShadowBuilder
对象。该字段设置为null
。您必须延长View.DragShadowBuilder
并替换其方法,否则您会收到 隐藏真实的拖动阴影。系统不会抛出错误。
View.DragShadowBuilder
类有两个方法,可共同创建拖动操作
阴影:
onProvideShadowMetrics()
在您调用
startDragAndDrop()
后,系统会立即调用该方法。使用该方法可以向系统发送拖动阴影的尺寸和接触点。该方法有两个参数:outShadowSize
:一个Point
对象。进入拖动阴影宽度x
,并将其高度存储在y
。outShadowTouchPoint
:一个Point
对象。接触点是 处于用户手指下方的拖动阴影内。 其 X 位置存储在x
中,Y 位置存储在y
中。onDrawShadow()
调用
onProvideShadowMetrics()
后,系统会立即调用onDrawShadow()
来创建拖动阴影。该方法具有单个 参数,即一个Canvas
对象, 系统会利用您在onProvideShadowMetrics()
。该方法会在提供的Canvas
。
为了提升性能,请保持较小的拖动阴影大小。对于单个 那么您可能需要使用图标如果选择了多个项目 希望使用堆栈中的图标,而不是在屏幕上展开的完整图片。
拖动事件监听器和回调方法
View
使用实现
View.OnDragListener
或视图的 onDragEvent()
回调方法。时间
系统调用该方法或监听器时,它会提供一个
DragEvent
参数。
在大多数情况下,使用监听器比使用回调方法更可取。设计界面时,您通常不需要为 View
类创建子类,但使用回调方法时,您必须创建子类来替换回调方法。相比之下,您可以实现一个监听器类,然后将其与多个不同的 View
对象配合使用。您还可以将其实现为匿名内联类
或 lambda 表达式。如需为 View
对象设置监听器,请调用
setOnDragListener()
。
作为替代方案,您可以更改 onDragEvent()
的默认实现。
而无需重写 方法。设置
OnReceiveContentListener
观看次数;有关详情,请参阅
setOnReceiveContentListener()
。
然后,onDragEvent()
方法将默认执行以下操作:
- 返回 true 以响应对
startDragAndDrop()
的调用。 通话
performReceiveContent()
如果拖放数据被放到了视图上。相应数据会传递到 方法指定为ContentInfo
对象。通过 方法会调用OnReceiveContentListener
。如果拖放数据被放到视图上,且
OnReceiveContentListener
会使用其中的任何内容。
定义 OnReceiveContentListener
来专门为您的 API 处理数据,
应用。要向后兼容到 API 级别 24,请使用
OnReceiveContentListener
。
您可以在以下位置为 View
对象添加拖动事件监听器和回调方法:
在这种情况下,系统会首先调用监听器。系统不会调用
回调方法,除非监听器返回 false
。
onDragEvent()
方法和 View.OnDragListener
的组合为
类似于
onTouchEvent()
和View.OnTouchListener
与触摸事件结合使用