优才网

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

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

一、拖放机制概述

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

² 同意以图形化的手势操作完毕某项任务。

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

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

² 拖放机制比自编程实现拖放操作更方便,长处包含:

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

2、系统自己主动推断手指的位置。

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

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

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

² 拖放机制包含:

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所看到的

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

当拖动时钟离开“启动”区域,在日志窗体显示: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;

}

}

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

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

    ι 版权声明:本文为博主原创文章,未经博主允许不得转载. Looper在Android的消息机制中就是用来进行消息循环的.它会不停地循环,去MessageQueue中查看是否有新消息,如果有消息就立刻 ...

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

    ι 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.为什么需要Android的消息机制 因为Android系统不允许在子线程中去访问UI,即Android系统不允许在子线程中更新UI. 为什 ...

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

    ι 版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一篇文章中,我们已经提到了ThreadLocal,它并非线程,而是在线程中存储数据用的.数据存储以后,只能在指定的线程中获取到数据,对于其 ...

  4. 讲讲Android事件拦截机制

    简介 什么是触摸事件?顾名思义,触摸事件就是捕获触摸屏幕后产生的事件.当点击一个按钮时,通常会产生两个或者三个事件--按钮按下,这是事件一,如果滑动几下,这是事件二,当手抬起,这是事件三.所以在And ...

  5. Android事件分发机制(上)

    Android事件分发机制这个问题不止一个人问过我,每次我的回答都显得模拟两可,是因为自己一直对这个没有很好的理解,趁现在比较闲对这个做一点总结 举个例子: 你当前有一个非常简单的项目,只有一个Act ...

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

    Android事件分发机制 该篇文章出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分 ...

  7. Android开发——Android的消息机制详解

    )子线程默认是没有Looper的,Handler创建前,必须手动创建,否则会报错.通过Looper.prepare()即可为当前线程创建一个Looper,并通过Looper.loop()来开启消息循环 ...

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

    自己定义Viewgrou中我们或许会常常碰到这种情况,2个子控件的事件冲突导致滑动没实用了.滑动反应非常慢,点击没用了,要划非常多次才移动一点点等等.或许我们第一反应就是百度,google去搜索下答案 ...

  9. Android之window机制token验证

    前言 很高兴遇见你~ 欢迎阅读我的文章 这篇文章讲解关于window token的问题,同时也是Context机制和Window机制这两篇文章的一个补充.如果你对Android的Window机制和Co ...

随机推荐

  1. Selenium2+python自动化18-加载Firefox配置【转载】

    前言有小伙伴在用脚本启动浏览器时候发现原来下载的插件不见了,无法用firebug在打开的页面上继续定位页面元素,调试起来不方便 . 加载浏览器配置,需要用FirefoxProfile(profile_ ...

  2. Selenium2+python自动化12-操作元素(键盘和鼠标事件)【转载】

    前言 在前面的几篇中重点介绍了一些元素的到位方法,到位到元素后,接下来就是需要操作元素了.本篇总结了web页面常用的一些操作元素方法,可以统称为行为事件 有些web界面的选项菜单需要鼠标悬停在某个元素 ...

  3. corosync基本使用

    相关rpm: corosync-2.4.0-4.el6.x86_64.rpm The Corosync Cluster Engine and Application Programming Inter ...

  4. Python的程序结构[1] -> 方法/Method[4] -> 魔术方法 __call__ / __str__ / __repr__

    __call__ 方法 __call__ 是当对象被调用时会调用的方法,允许一个对象(类的实例等)像函数一样被调用,也可以传入参数. 1 class Foo(): 2 def __init__(sel ...

  5. #424 Div2 E

    #424 Div2 E 题意 给出一个 n 个数的数列,从前往后取数,如果第一个数是当前数列的最小值,则取出,否则将它放到数列尾端,问使数列为空需要多少步操作. 分析 用数据结构去模拟. 线段树维护区 ...

  6. 818D - Multicolored Cars

    818D - Multicolored Cars 题意 在 1 到 n 时刻,有 n 量有颜色的车通过,用数字表示颜色,Alice 选择一个颜色A,要求 Bob 选择一个颜色B,使得对于任意时刻 cn ...

  7. java Iterable

    Iterable

  8. hdu 1506 Largest Rectangle in a Histogram 构造

    题目链接:HDU - 1506 A histogram is a polygon composed of a sequence of rectangles aligned at a common ba ...

  9. Oracle PL/SQL入门之慨述

    Oracle PL/SQL入门之慨述 一.PL/SQL出现的目的 结构化查询语言(Structured Query Language,简称SQL)是用来访问关系型数据库一种通用语言,它属于第四代语言( ...

  10. Spring Boot特点

    特点: 1.化繁为简,简化配置 2.备受关注,是下一代框架 3.为服务的入门级框架