为什么要拖放?
拖放在某些UI交互中可以简化用户操作。

拖放的步骤包括哪些?
“Drag and Drop”,拖放,顾名思义,总共就分三步:
1, 开始拖起来;
2, 正在拖;
3, 放下,进行操作;
在这三步里,贯穿的是数据的传输,从拖的地方传输到放的地方。

现在,我们就以一个简单的拖放删除笔记的App来讲解上面三个步骤都怎么实现的。
App见截图,拽住上面的笔记,然后拖至底下的垃圾桶然后放开,笔记就被删除了。

1,开始拖拽:
开始拖拽要解决三个问题:
1, 什么时候开始?如何开始?
一般是在用户长按一个组件的时候,我们开始拖拽,所以给要被拖拽的View定义它的OnLongClickListener,在其中调用View.startDrag()方法就可以了。
startDrag()方法的定义:

1
2
boolean android.view.View.startDrag(
ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)

第一个参数ClipData data是拖拽的对象,下面第2条来讲解;第二个参数DragShadowBuilder shadowBuilder是拖拽时的样子,下面的第3条来讲解。

2, ClipData:拖拽的数据实现?
数据定义通过ClipData和ClipData.Item来定义,看一下它们的定义:

1
2
3
4
5
6
7
8
9
/**
* Added in API level 11
* Create a new clip.
* Parameters
* label Label to show to the user describing this clip.
* mimeTypes An array of MIME types this data is available as.
* item The contents of the first item in the clip.
*/
public ClipData (CharSequence label, String[] mimeTypes, ClipData.Item item)

由此可见,构造一个ClipData对象,作为拖拽的数据对象,它的构造需要三个参数:
1,label 给一个标签;
2,mimeTypes
3,一个ClipData.Item对象
再来看ClipData.Item的定义:

1
2
3
4
5
6
7
8
9
10
11
12
/**
* The types than an individual item can currently contain are:
* Text: a basic string of text. This is actually a CharSequence, so it can be formatted text supported
* by corresponding Android built-in style spans. (Custom application spans are not supported and will be
* stripped when transporting through the clipboard.)
* Intent: an arbitrary Intent object. A typical use is the shortcut to create when pasting a clipped item
* on to the home screen.
* Uri: a URI reference. This may be any URI (such as an http: URI representing a bookmark),
* however it is often a content: URI. Using content provider references as clips like this allows
* an application to share complex or large clips through the standard content provider facilities.
*/
android.content.ClipData.Item

ClipData.item有三类构造方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Create an Item consisting of a single block of (possibly styled) text.
*/
public Item(CharSequence text) {
} /**
* Create an Item consisting of a single block of (possibly styled) text,
* with an alternative HTML formatted representation. You must
* supply a plain text representation in addition to HTML text; coercion
* will not be done from HTML formated text into plain text.
*/
public Item(CharSequence text, String htmlText) {
} /**
* Create an Item consisting of an arbitrary Intent.
*/
public Item(Intent intent) {
} /**
* Create an Item consisting of an arbitrary URI.
*/
public Item(Uri uri) {
}

就是分别可以用Text, Intent和Uri来构造。

3, DragShadowBuilder: 拖拽时的样子:

DragShadowBuilder可以用来定义拖拽时的样子,可以直接用其构造方法DragShadowBuilder(View view)来传递一个View做为样子,也可以自己扩展DragShadowBuilder类。
看一下DragShadowBuilder(View view)的构造方法说明:

1
2
3
4
5
6
7
8
9
/**
* Added in API level 11
* Constructs a shadow image builder based on a View. By default, the resulting drag shadow will have the same appearance and
* dimensions as the View, with the touch point over the center of the View.
* Parameters
* view A View. Any View in scope can be used.
*/
public View.DragShadowBuilder (View view)

OK,拖拽的第一阶段:开始拖拽就讲完了,看一下完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//给要被拖拽的View mNote_1添加长按事件
mNote_1.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//在我的代码实现中,给mNote_1设置了一个Text作为其Tag,这里取出来用来构造Item
ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());
String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
//构造一个drag data
ClipData dragData = new ClipData(v.getTag().toString(), mimeTypes, item);
//构造一个shadow
View.DragShadowBuilder myShadow = new DragShadowBuilder(mNote_1);
//发起拖拽
v.startDrag(dragData, myShadow, null, 0);
return true;
}
});

2,正在拖拽

只要给View添加一个OnDragListener,就可以得到整个拖拽过程中的所有回调事件。
OnDragListener的方法onDrag定义如下:

1
2
3
4
5
6
7
8
9
10
/**
* Added in API level 11
* Called when a drag event is dispatched to a view. This allows listeners to get a chance to override base View behavior.
* Parameters
* v The View that received the drag event.
* event The DragEvent object for the drag event.
* Returns
* true if the drag event was handled successfully, or false if the drag event was not handled. Note that false will trigger the View to call its onDragEvent() handler.
*/
public abstract boolean onDrag (View v, DragEvent event)

DragEvent定义了所有拖拽中的事件:

ACTION_DRAG_STARTED
只在应用程序调用startDrag()方法,并且获得了拖拽影子后,View对象的拖拽事件监听器才接收这种事件操作。
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,放下的操作 
放下就是响应上面说的ACTION_DRAG_ENDED事件。在具体应用中,要明确我们是在哪里放下才采取动作。本文的例子中,就是把作为笔记的TextView拖拽到一个垃圾桶标志的ImageView上放下时,采取删除该TextView的操作。
只要给垃圾桶ImageView添加OnDragListener并且监听到ACTION_DRAG_ENDED事件时采取操作就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
trashView.setOnDragListener( new OnDragListener(){
@Override
public boolean onDrag(View v, DragEvent event){
switch(event.getAction())
{
case DragEvent.ACTION_DROP:
Log.d("trash view", "ACTION_DROP event");
ClipData data = event.getClipData();
CharSequence noteName = data.getItemAt(0).getText();
if(noteName.equals(TAG_NOTE_1)) {
mNote_1.setVisibility(View.GONE);
Toast.makeText(MainActivity.this, "Note 1 has been removed.", Toast.LENGTH_SHORT).show();
} else if(noteName.equals(TAG_NOTE_2)) {
Toast.makeText(MainActivity.this, "Note 2 has been removed.", Toast.LENGTH_SHORT).show();
mNote_2.setVisibility(View.GONE);
}
break;
default:
break;
}
return true;
}
});

Android客户端的图形化拖放操作的设计实现的更多相关文章

  1. 一脸懵逼学习oracle(图形化界面操作---》PLSQL图形化界面)

    1:经过几天的折腾,终于将oracle安装成功,创建用户,授权等等操作,接下来就安安心心学习oracle: 安装好PLSQL图形化界面和汉化以后(过程自己百度吧,百度more and more),登录 ...

  2. mac电脑批量解压android apk文件图形化工具--apkDecode

    mac电脑apk文件解压软件,简单的用图形界面将apktools包装了下,使用起来非常简单,可以将apk文件批量解压缩,方便大家查看一些东东,仅供学习目的. 使用步骤如下: 1 下载apkDecode ...

  3. [原创]WB Android客户端架构总结:发WB工作队列设计

    先简单说下需求,发一条WB包含多种类型,例如图片.视频.文字等,发送工作不能阻塞UI,工作队列易于扩展,方便优化. 几个重要的类: JobManager:统一管理Job列表,包括job的添加.启动.终 ...

  4. 6、Docker图形化管理(Portainer)

    一.Portainer简介 Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控 ...

  5. Sourcetree使用 - git图形化工具(三)

    前面两个章节总结了Sourcetree的安装与配置Sourcetree密钥,这个章节主要讲如何使用Sourcetree.以前呢,都是使用git Bash进行命令行方式进行操作git,感觉部分时间浪费在 ...

  6. VMware Workstation 15 Pro安装带图形化界面的CentOS7

    1.双击打开“VMware Workstation”,然后选择“创建新的虚拟机” 2.在安装向导中,选择“稍后安装操作系统”,然后点击“下一步”继续安装 3.在“客户机操作系统”中选择“Linux(L ...

  7. FOFA 批量采集url 图形化界面编写

    这是脚本 # coding:utf- import requests,re import time import sys import getopt import base64 guizhe='' s ...

  8. Git各大平台(win/Linux/Mac)图形化界面客户端大汇总

    摘要: 介绍各平台下的图形化界面git客户端(本人并没有全部使用过),欢迎大家补充新的软件或者使用感受~  一.TortoiseGit - The coolest Interface to Git V ...

  9. [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit

    [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit 读前必备: 接上篇: 分布式版本控制系统Git——使用GitS ...

随机推荐

  1. Centos 6.0将光盘作为yum源的设置方法

    在使用Centos 的时候,用yum来安装软件包是再方便不过了,但是如果在无法连接互联网的情况下,yum就不好用了. 下面介绍一种方式,就是将Centos安装光盘作为yum源,然后使用yum来安装软件 ...

  2. js 实现动态key value(JSON字符串注意事项:key和value都要用双引号,官网指定用双引号)

    1.JSON字符串注意事项:key和value都要用双引号,官网指定用双引号,如下: var mapStr='{"a":"a","b":&q ...

  3. PHP_php.ini_说明详解

    这个文件必须命名为''php.ini''并放置在httpd.conf中的PHPIniDir指令指定的目录中.最新版本的php.ini可以在下面两个位置查看:http://cvs.php.net/vie ...

  4. 60行JavaScript俄罗斯方块

    <!doctype html><html><head></head><body> <div id="box" st ...

  5. DB服务器中的参数优化

    1.swappiness 禁止系统使用swap空间,配置/etc/sysctl.conf中的vm.swappiness=0 2.Scheduler调度 Scheduler调度,指的是磁盘的IO调度算法 ...

  6. ie6下absolute:fixed问题,完美兼容

    普通css代码 .fix_foot{height: 30px; background: #ff0000; position: %; z-index:;} ie6兼容代码 * html,* html b ...

  7. Redis学习——链表源码分析

    0. 前言 Redis 中的链表是以通用链表的形式实现的,而对于链表的用途来说,主要的功能就是增删改查,所以对于查找来说,redis其提供了一个match函数指针,用户负责实现其具体的匹配操作,从而实 ...

  8. oracle安装常见问题

    版本信息:CentOS6.5 + oracle11G 1.监视器颜色错误: [oracle@bogon database]$ 正在启动 Oracle Universal Installer... 检查 ...

  9. Elmah 日志记录组件

    http://www.cnblogs.com/jys509/p/4571298.html 简介 ELMAH(Error Logging Modules and Handlers)错误日志记录模块和处理 ...

  10. [Unity3D][转] 关于Assets资源目录结构管理

    分享个我们项目常用的目录结构,微调过很多次,最终到了这个版本.个人认为这种管理资源方式是不错的.欢迎探讨各个细节~ 更新于2013.5.30   Asserts   --Editor 自写的灵活方便插 ...