【优才原创】Android的拖放机制

优才网

【优才原创】Android的拖放机制

2016-04-18 优才学院 优才网

一、拖放机制概述

2 拖放操作是手指触摸屏幕上的某一对象,然后拖动该对象,最后在屏幕的某个位置释放该对象并执行某种操作,如删除、卸载、启动、复制数据等。

2 允许以图形化的手势操作完成某项任务。

2 拖放操作的优势:直观、易用、简化操作步骤。

2 SDK3.0提供了支持拖放操作的编程机制,简称拖放机制,拖放机制是为数据移动设计的,但能够用于其它的UI操作。如Android系统自带的将托盘内图标代表的应用程序以拖放的方式卸载。

2 拖放机制比自编程实现拖放操作更方便,优点包括:

1、提供了对所有View支持拖放操作的API,无需自定义View。

2、系统自动判断手指的位置。

3、由系统自动绘制影子图形。

4、系统提供了拖放对象与目标对象之间传递数据的机制,简化了数据传递的编程。

5、提供了更多的拖放事件,如按下、抬起、释放、进入目标区域、仍在目标区域、离开目标区域、结束拖放等六个事件。并且这些事件由系统捕捉、发送,开发者只需编写处理这些事件的代码。

2 拖放机制包括:

1、响应拖放操作事件的接口;

2、存放拖放操作相关信息的类;

3、启动拖放操作的方法;

4、绘制拖放过程中影子图形的类;

5、传递数据的类。

(二)拖放编程步骤

步骤1、设置被拖放对象的点击或长按或触摸的事件响应代码,在该响应代码中完成以下操作:

1)设置传送给目标对象的数据;

2)设置拖放过程中绘制影子图形的对象;

3)启动拖放操作。

步骤2、编写被拖放对象和拖放目标对象的响应拖放事件的代码。

(三)相关类-ClipData

1、概述

ClipData类用于操作剪贴板中的数据,该类支持进程之间传递数据。在拖放编程中,该类负责被拖动对象与拖动对象之间的数据传递,该类支持传递Uri、Html文本、纯文本等多种类型的数据。

2、常用方法


public static
ClipData newPlainText (CharSequence label,

CharSequence text)


作用


创建一个新的ClipData对象,该对象包含MIMETYPE_TEXT_PLAIN类型的数据。


参数


label:代表剪贴板中text数据的键。

text:剪贴板中的数据。


public ClipData.Item getItemAt (int index)


作用


返回剪贴板中的数据。


参数


index:数据的索引值。index的值范围[0,getItemIndex-1]


说明


若剪贴板中存放的是字符串数据,则由以下代码取出该字符串数据:

new ClipData().getItemAt(0).getText().toString();

其中索引值0表示取出的是剪贴板中第一个


public ClipData.Item getItemAt (int index)


作用


返回剪贴板中的数据。

(四)相关类-DragShadowBuilder

1、概述

在拖拽和放下操作期间,系统会显示一张用户拖动的图片。对于要移动的数据,这张图片就代表了被拖动的数据。对于操作,这张图片就代表了拖动操作的某些外观。

这张图片被叫做影子图形,由DragShadowBuilder对象来创建。

DragShadowBuilder类是View类的内部类。

2、构造方法


public View.DragShadowBuilder (View view)


作用


封装了拖拽中各种事件和控件的位置等信息。


参数


创建用于绘制影子图形的对象,该对象的基类是View,默认情况下,该影子图形与被拖动图形尺寸相同,影子图形的中心点是View对象的中心点坐标。


参数


view:被拖拽的View对象。

3、与拖拽相关的方法


public final boolean startDrag (ClipData data,

View.DragShadowBuilder shadowBuilder,

Object myLocalState, int flags)


作用


开始拖拽指定的View,并把该对象传递给系统。


参数


创建用于绘制影子图形的对象,该对象的基类是View,默认情况下,该影子图形与被拖动图形尺寸相同,影子图形的中心点是View对象的中心点坐标。


参数


参数-data:存放数据的剪贴板对象。

shadowBuilder:操作影子图片的对象。

myLocalState:被拖动对象与目标对象之间传递数据的轻量级结构的对象。


参数


flags:用于控制拖拽操作的类型,当前未定该标志值尚未定义,设置0即可。

(五)相关接口-OnDragListener

1、概述

OnDragListener接口用于响应拖拽的相关事件。

2、接口中声明的方法


public boolean onDrag(View
view, DragEvent event)


作用


封装了拖拽中各种事件和控件的位置等信息。


参数


view:当前操作的对象,包括被拖拽对象和拖放的目标对象。


返回值


false将不会接收后续的拖动事件

true将接收后续的拖动事件。

(六)相关类-DragEvent

1、概述

系统用DragEvent对象存储拖放事件的相关信息。DragEvent对象包含了一个操作类型,用于告诉监听器在拖放过程中发生的事件。该对象还根据操作类型,包含了其它的数据。

2、拖放事件常量


常量


作用


ACTION_DRAG_STARTED


调用startDrag()方法,并且获得了拖拽影子后,View对象的拖拽事件监听器才接收这种事件操作


ACTION_DRAG_ENTERED


进入目标View区域


ACTION_DRAG_LOCATION


停留在目标View区域


ACTION_DRAG_EXITED


离开目标View区域


ACTION_DROP


释放拖拽操作


ACTION_DRAG_ENDED


结束拖拽操作

有六种与拖放相关的事件,这些事件在DragEvent类中用六个常量表示,如下表所示:


常量


含义


ACTION_DRAG_ENTERED


当拖拽影子刚进入目标View对象的边框时,View对象的拖拽事件监听器会接收这种事件操作类型。


ACTION_DRAG_LOCATION


在View对象收到一个

ACTION_DRAG_ENTERED事件之后,并且拖拽影子依然还在这个对象的边框之内时,这个View对象的拖拽事件监听器会接收这种事件操作类型。


ACTION_DRAG_EXITED


View对象收到一个ACTION_DRAG_ENTERED和至少一个ACTION_DRAG_LOCATION事件之后,这个对象的事件监听器会接受这种操作类型。


ACTION_DROP


当用户在一个View对象之上释放了拖拽影子,这个对象的拖拽事件监听器就会收到这种操作类型。如果这个监听器在响应ACTION_DRAG_STARTED拖拽事件中返回了true,那么这种操作类型只会发送给一个View对象。如果用户在没有被注册监听器的View对象上释放了拖拽影子,或者用户没有在当前布局的任何部分释放操作影子,这个操作类型就不会被发送。如果View对象成功的处理放下事件,监听器要返回true,否则应该返回false。


ACTION_DRAG_ENDED


当系统结束拖拽操作时,View对象拖拽监听器会接收这种事件操作类型。这种操作类型之前不一定是ACTION_DROP事件。如果系统发送了一个ACTION_DROP事件,那么接收ACTION_DRAG_ENDED操作类型不意味着放下操作成功了。监听器必须调用getResult()方法来获得响应ACTION_DROP事件中的返回值。如果ACTION_DROP事件没有被发送,那么getResult()会返回false。

3、常用方法


public int getAction ()


作用


返回拖拽的类型,该类型的可能值是以上的六个常量。


public
ClipData  getClipData()


作用


返回ClipData类型的对象,该对象中封装了被拖拽对象的数据。


提示


ClipData对象在拖拽开始时创建;只有DragEvent. ACTION_DROP事件发生时,getClipData()才能返回startDrag()中第一个参数代表的ClipData对象。


public float getX()


作用


返回拖拽对象的横坐标。


public float getY()


作用


返回拖拽对象的纵坐标。


public Object getLocateState()


作用


获取startDrag()中的第三个参数。

二、【案例】

目标

在屏幕左上有一个时钟图片,屏幕下边有三个标签,分别代表卸载、启动和分享,如图4所示:

长按时钟,在日志窗口显示“开始拖拽clock,拖动时钟时,如图-5所示:

当拖动时钟进入到“启动”标签区域,在日志窗口显示:clock进入启动区,clock仍在启动区,入图-6所示

当拖动时钟离开“启动”区域,在日志窗口显示:clock离开启动区。松开时钟将显示拖放结束。

提示:

当进入目标区域时,即使没有松手,仍会发生ACTION_DROP事件,因此在图-7中显示“启动clock”。

当进入“卸载”、“分享”区域时,在日志窗口中也将显示类似图-6、图-7的信息。

思路

步骤1、MainActivity实现拖放的相关接口

public class MainActivity
extends Activity
implements OnDragListener,OnLongClickListener{

步骤2、定义MainActivity的成员

ImageView
mivClock;

TextView
mtvUninstall,mtvStart,mtvShare;

步骤3、初始化控件

private void initView()
{

//创建显示时钟的控件

mivClock=(ImageView)
findViewById(R.id.ivClock);

//设置时钟拖拽事件的响应

mivClock.setOnDragListener(this);

//设置长按时间的响应

mivClock.setOnLongClickListener(this);

//创建代表分享、启动和卸载的三个控件

mtvShare=(TextView)
findViewById(R.id.tvShare);

mtvStart=(TextView)
findViewById(R.id.tvStart);

mtvUninstall=(TextView)
findViewById(R.id.tvUninstall);

//设置三个TextView响应拖拽事件的代码

mtvShare.setOnDragListener(this);

mtvStart.setOnDragListener(this);

mtvUninstall.setOnDragListener(this);

}

步骤4、编写响应拖放事件的代码

//响应拖拽事件

@Override

public boolean onDrag(View
view, DragEvent event) {

boolean result=true;

//获取拖拽的动作类型值

int action=event.getAction();

switch (action)
{

case DragEvent.ACTION_DRAG_STARTED:

if(view.getId()==R.id.ivClock){

Log.i("main","开始拖拽clock");

}

break;

case DragEvent.ACTION_DRAG_ENTERED:

if(view.getId()==R.id.tvStart){

Log.i("main","clock进入启动区");

}

break;

case DragEvent.ACTION_DRAG_EXITED:

if(view.getId()==R.id.tvStart){

Log.i("main","clock离开启动区");

}

case DragEvent.ACTION_DRAG_LOCATION:

if(view.getId()==R.id.tvStart){

Log.i("main","clock仍在启动区");

}

case DragEvent.ACTION_DROP:

if(view.getId()==R.id.tvShare){

Log.i("main","分享clock");

}else if(view.getId()==R.id.tvStart){

Log.i("main","启动clock");

}else if(view.getId()==R.id.tvUninstall){

Log.i("main","卸载clock");

}

break;

case DragEvent.ACTION_DRAG_ENDED:

Log.i("main","拖拽结束,在drop事件之后发生");

break;

default:

result=false;

break;

}

return result;

}

步骤5、编写响应长按事件的代码

//长按事件响应程序

@Override

public boolean onLongClick(View
view) {

//创建实现阴影的对象

DragShadowBuilder builder=new DragShadowBuilder(view);

/*开始拖拽并把view对象传递给系统。作为响应startDrag()方法的一部分,

*

系统调用在View.DragShadowBuilder对象中定义的回调方法

*

来获取拖拽影子。

*/

view.startDrag(null,
builder, null,
0);

return true;

}

}

时间: 2024-10-20 16:06:20

【优才原创】Android的拖放机制的相关文章

【原创】源码角度分析Android的消息机制系列(五)——Looper的工作原理

ι 版权声明:本文为博主原创文章,未经博主允许不得转载. Looper在Android的消息机制中就是用来进行消息循环的.它会不停地循环,去MessageQueue中查看是否有新消息,如果有消息就立刻处理该消息,否则就一直等待. Looper中有一个属性: static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); 这也就解释了,前面我们所说的我们可以通过ThreadLocal实现Looper

Android性能调优篇之探索垃圾回收机制

详细内容请查看我的简书地址:Android性能调优篇之探索垃圾回收机制 或者我的个人博客地址:Android性能调优篇之探索垃圾回收机制

【原创】源码角度分析Android的消息机制系列(二)——ThreadLocal的工作过程

ι 版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一篇文章中,我们已经提到了ThreadLocal,它并非线程,而是在线程中存储数据用的.数据存储以后,只能在指定的线程中获取到数据,对于其他线程来说是无法获取到数据的,也就是说ThreadLocal可以在多个线程中互不干扰地存储和修改数据.基于ThreadLocal的这一特点,那么当我们在开发中,需要将某些数据以线程作为作用域,并且不同线程具有不同的数据副本的时候,就可以考虑采用ThreadLocal了. Android的消息机制中也

【原创】源码角度分析Android的消息机制系列(一)——Android消息机制概述

ι 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.为什么需要Android的消息机制 因为Android系统不允许在子线程中去访问UI,即Android系统不允许在子线程中更新UI. 为什么不允许在子线程中更新UI呢?因为Android的控件不是线程安全的.既然是非线程安全的,那么若在多个子线程中并发访问,UI控制可能会处于一种不可预期的状态.有的读者可能会说,为什么不对UI控件加锁呢?加锁会降低UI访问的效率,因为加锁之后,若想要运行这段synchronized的代码,线程要先拿到

【自定义控件】android事件分发机制

自定义控件中我们经常也许会经常碰到这样的情况,自己加了一些点击,滑动的事件的处理判断导致另外一些控件点击,滑动没有用了,滑动反应反应很慢,要划很多次猜移动一点点等等.也许我们第一反应就是百度,google去搜索下答案,把代码直接copy过来.其实也许可以换个解决办法,自己想想为什么会出现这种情况. 以下是博主对android事件分发机制的初步探索.希望大家看完后能对Android事件分发机制有一个详细的了解,以后不用百度,google也能轻松解决由于事件冲突导致各种问题. 首先我们要对Andro

Android事件分发机制详解:史上最全面、最易懂

前言 Android事件分发机制是每个Android开发者必须了解的基础知识 网上有大量关于Android事件分发机制的文章,但存在一些问题:内容不全.思路不清晰.无源码分析.简单问题复杂化等等 今天,我将全面总结Android的事件分发机制,我能保证这是市面上的最全面.最清晰.最易懂的 本文秉着"结论先行.详细分析在后"的原则,即先让大家感性认识,再通过理性分析从而理解问题: 所以,请各位读者先记住结论,再往下继续看分析: 文章较长,阅读需要较长时间,建议收藏等充足时间再进行阅读 目

图解 Android 事件分发机制

首发原文:http://mp.weixin.qq.com/s?__biz=MzI0MjE3OTYwMg==&mid=2649548149&idx=1&sn=709149df682c7d3a6e453c9ef0626a1f&chksm=f1180e08c66f871eb2e7e39e057a5b090214fd71adcd98aa36b3d7fcecf77ad5d08138c50131#rd 在Android开发中,事件分发机制是一块Android比较重要的知识体系,了解并熟

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识.也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图片使用Button而不用Ima

[转]Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

Android事件分发机制 该篇文章出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识. 也有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的 功能,ListView就不能滚动了?为什么图片轮播器里的图