android 拖放模型

英文原文:

ps:时间过去好久了,这篇文章一直在我的网易云笔记里面丢着。我自己都忘了这是我摘抄的网上的童鞋的,还是自己翻译的。

应该是生成于2013年10月17日,大概在我当时在写android Launcher的项目时记录的。

为了不侵犯别个的权益,聪明的我在文章里捡了几句话百度了一下,,发现有类似的翻译但是措辞像我这么犀利的好像没有。于是权当作自己翻译的吧。

是的,不要怀疑我,英语四级将将及格也是可以翻译技术性文章的。

API Level 11加入 (android 3.0)

通过安卓的拖放框架,你可以允许用户使用图像拖放手势将数据从当前布局的一个view移动到另一个view。这个框架包括一个拖动事件类,拖动监听器,和一些辅助的方法和类。 虽然这个框架主要是为数据移动设计的,但你也可以为其他的界面动作使用它。比如你可以创建一个应用当用户把一个颜色图标拖动到另一个图标上时混合两种颜色。这个主题的剩下部分,描述了数据移动的框架。概述 当用户做了一些你可以识别为开始拖动数据的手势,一个拖放操作就开始了。作为回应,你的应用程序告诉系统拖动开始了。系统回调你的应用程序来获得正在被拖动的数据的描述。当用户的手指在当前布局移动这个描述(一个拖动阴影),系统发送拖动事件给拖动事件监听器对象和与布局中与view对象联系在一起的拖动事件回调方法。一旦用户释放这个拖动阴影,系统就结束拖动操作。 你可以创建一个拖动事件监听器,通过一个实现View.OnDragListener()的类。通过setOnDragListener()绑定到view。每个view都有一个onDragEvent()的回调函数。它们的更多细节在拖动事件监听器和回调方法一节。 注意:简单起见,接下来的章节我们称呼接收拖动事件的例程为拖动事件监听器,哪怕它其实实际上是一个回调方法。 当你开始一个拖动,你包括正在移动的数据和描述该数据的元数据作为调用系统的一部分。在拖动期间,系统发送拖放事件到监听器或者布局中每个view的回调函数。当拖动停止的时候,监听器或者回调函数通过metadata来决定他们是否接受这个拖动。如果接受,系统则把拖动事件的数据发送到监听器和回调函数。 你的应用程序通过调用startDrag()来告诉系统开始一个拖动。这告诉系统开始发送拖动事件,同事也发送你拖动的数据。 你可以为当前布局中的其他附加view调用startDrag(),系统知识通过这个view对象来获取你布局中的全局配置的属性。 一旦你的应用程序调用了startDrag(),剩下的流程使用系统发送给view对象的event。拖放流程 拖放过程主要有四个步骤或者状态:Started 响应用户的手势开始一个拖动,应用程序调用startDrag()来告诉系统启动一个拖动。startDrag()的参数提供了被拖动的数据,它的metadata,还有绘制拖动阴影的回调。 系统首先通过回调到应用程序来获取拖动阴影,然后再设备上显示拖动阴影。 接下来,系统发送action type为ACTION_DRAG_STARTED的拖动事件给当前布局上所有view对象的拖动事件监听器。为了继续接受拖动事件,包括可能的drop事件,监听器必须返回true.这是向系统注册监听器。只有注册过的监听器才能继续接收拖动事件。在这一点上,监听器也可以改变他们view对象的外观来表示监听器能接收拖动事件。 如果监听器返回false,那么它将不能接收当前操作的拖动事件直到系统发送了一个action type为ACTION_DRAG_ENDED的拖动事件。通过发送false,监听器告诉系统,它对这个拖动操作不感兴趣,不想继续接收拖动数据。Continuing 用户继续拖动。当拖动阴影贯穿view对象的边框,系统会发送一个或多个拖动事件给view对象的拖动监听器(如果已经注册接收事件)。监听器可能选择改变view对象的外观来响应事件。比如,如果事件表示拖动阴影进入view(action typeACTION_DRAG_ENTERED)的边框区域,监听器可以高亮view来响应。Dropped 用户在一个能接收它的view的边框区释放拖动阴影。系统发送给view对象一个action type为ACTION_DROP的拖动事件。该拖动事件包含了在启动这个操作时候通过startDrag()操作传给系统的数据。如果代码接收成功,监听器被期望返回true给系统。 注意,这一步只发生在当用户在其监听器被注册接收拖动事件的view的边框区放下拖动阴影时。如果用户在其他任何情况下释放拖动阴影,则没有ACTION_DROP拖动事件被发送。Ended 在用户释放拖动阴影后,在系统发送ACTION类型为ACTION_DROP的拖动事件后,系统发送一个ACTION类型为ACTION_DRAG_ENDED的拖动事件来表示拖动操作结束。这样做是不管用户在哪释放了拖动阴影。这个事件被发送给每一个注册接收拖动事件的监听器,即使监听器接收到了ACTION_DROP事件。拖动事件监听器和回调方法 一个view可以通过实现View.OnDragListener的拖动事件监听器或者view的onDragEvent方法来接收拖动事件。当系统调用回调方法或者监听器时,传递给他们一个DragEvent对象。 大多数情况下你可能会更想用监听器。当设计界面时,通常不用子类化view类,但是使用回调函数强迫你必须这么做,为了重写方法。比较而言,你可以实现一个监听器类,然后在几个不同的view对象使用它。你还可以以匿名内部类的方式实现监听器。把监听器绑定给view对象,需要调用setOnDragListener()。 你可以再一个view对象中同时有监听器和回调方法。这种情况下,系统首先调用监听器。除非监听器返回false,否则系统不会继续调用回调方法。 onDragEvent(DragEvent) 和View.OnDragListener的联系就好像在触摸事件中onTouchEvent() 和View.OnTouchListener的关系。拖动事件 系统以DragEvent对象的形式发出一个拖动事件。这个对象包含了一个action类型,用来告诉监听器在拖放过程中发生了什么。这个对象还包含了其他数据,依据action类型。 为了获取action类型,监听器调用getAction()。有六种可能的值,在DragEvent类中以常量的形式定义。 拖动事件对象还包含了应用程序在startDrag()中提供给系统的数据。有些数据只有在特定的action类型时才有效。 getAction(), describeContents(), writeToParcel(), 和toString()总是返回有效数据。 如果方法不包含有效数据,则依据其返回值类型,返回null或者0.拖动阴影 在一个拖放操作中,系统显示一个用户拖动的图像。对于数据移动,这张照片代表了被拖动的数据。对其他操作,图像代表了一些方面的拖动操作。 这个图像被称作拖动阴影。你可以使用你View.DragShadowBuilder对象声明的方法创建它,然后当你开始一个拖动的时候使用startDrag()传递给系统。作为startDrag()的响应,系统调用你在View.DragShadowBuilder中定义的回调方法来获得一个拖动阴影。 View.DragShadowBuilder有两个构造器: View.DragShadowBuilder(View) View.DragShadowBuilder() View.DragShadowBuilder有两个方法: onProvideShadowMetrics() onDrawShadow() 为了提高性能,你应当保持这个拖动阴影的尺寸足够小。单个项目中,你可能使用一个图标。多个项目中,你可能想要使用栈中的图标,而不是展开在屏幕的完整图像。设计一个拖放操作 这一节一步步展示了如何开始一个拖动,如何想要拖动过程中的事件,如何响应放开事件,如何结束拖放操作。开始一个拖放 用户通过一个拖动手势来开始一个拖动,通常是在一个view对象的长按。作为响应,你应当; 1、必要时为正要被移动的数据创建ClipData和ClipData.Item。ClipData提供存储在其内部ClipDescription对象的元数据。对于不代表数据移动的拖放操作,你可能希望通过null来代替实际的对象。 比如, 2、以下代码片段定义了myDragShadowBuilder.它为拖动一个文本视图创建了一个小的灰色举行作为拖动阴影。 注意:你并不是必须要继承View.DragShadowBuilder.构造器View.DragShadowBuilder(View)以触碰点为中心创建一个默认的跟传入的view一样大小的拖动阴影。响应一个拖动开始 在拖动操作过程中,系统分发拖动事件给当前布局中view对象的拖动事件监听器。监听器应当通过调用getAction()来获取action类型。在拖动的开始,这个方法返回ACTION_DRAG_STARTED. 响应一个ACTION_DRAG_STARTED的事件,监听器需要如下做: 1、调用getClipDescription()来获取ClipDescription。使用ClipDescription中的MIME类型方法来看是否监听器能接收正在被拖动的数据。 如果拖放操作不代表数据移动,这可能不是必须的。 2、如果监听器能接收放开,它应当返回true。这告诉系统继续发送拖动事件给该监听器。如果不能接收放开事件,应当返回false,系统就会停止发送拖动事件直到发出ACTION_DRAG_ENDED。 注意:对于一个ACTION_DRAG_STARTED事件,DragEvent中的getClipData() \ getX() \ getY() \ getResult()是无效的。处理拖动过程中的事件 在拖动过程中,对ACTION_DRAG_STARTED拖动事件返回true作为响应的监听器会继续接收拖动事件。监听器在拖动过程中接收到的拖动事件的类型,取决于拖动阴影的位置和监听器view的可见性。 在拖动过程中,监听器主要使用拖动事件来决定是否应当改变view的外形。 在拖动过程中,getAction()返回下面3个值中的一个:ACTION_DRAG_ENTERED:当触碰点进入监听器的view的边框区时,监听器接收到这个事件。ACTION_DRAG_LOCATION:一旦监听器接收到ACTION_DRAG_ENTERED事件,在它接收到ACTION)DRAG_EXITED之前,触碰点每次移动都会接收到一个新的ACTION_DRAG_LOCATION事件。getX和getY方法返回触碰点的坐标。ACTION_DRAG_EXITED:在拖动阴影不再在该监听器的view的边框区之内,这个事件发送给一个以前接收到ACTION_DRAG_ENTERED的监听器。 监听器不需要响应其他action类型。如果监听器返回一个值给系统,将被忽略。下面是一些响应这些action类型的指导: 响应ACTION_DRAG_ENTERED和ACTION_DRAG_LOCATION,监听器可以改变view的外形来表示它可以接收放开。 action类型为ACTION_DRAG_LOCATION的事件包含getX和getY的有效数据,对应触碰点的位置。监听器可能需要这些信息来改变在触碰点上的view的外形。监听器也可以使用这些信息来决定用户将要放开拖动阴影的准确位置。 响应ACTION_DRAG_EXITED,监听器需要重置为响应ACTION_DRAG_ENTERED或ACTION_DRAG_LOCATION而改变的外形。这表明这个view不再是放开目标。响应放开 当用户在应用程序的view上释放拖动阴影,并且这个view之前已经报告它可以接收正在被拖动的内容,系统会分发一个类型为ACTION_DROP的事件给这个view.监听器需要如下做: 1.调用getClipData()来获取最初是由startDrag()提供的ClipData对象,并存储它。如果拖放操作不是代表数据移动,这不是必须的。 2.返回true表示放开操作被成功处理,false表示不成功。ACTION_DRAG_ENDED事件的getResult()的值作为返回值。 注意;如果系统没有发出ACTION_DROP事件,ACTION_DRAG_ENDED的getResult()返回false。 对于ACTION_DROP事件,getX和getY返回在放开时拖动点的位置,使用接收这个放开的view的坐标系统。 系统允许用户在一个不接收拖动事件的view上释放拖动阴影。也允许用户在应用程序界面的空区域,或者应用程序之外的区域释放拖动阴影。在这些情况下,系统不会发出一个ACTION_DROP事件,但它会发送ACTION_DRAG_ENDED事件。响应拖动结束 用户一释放拖动阴影,系统就发送一个ACTION_DRAG_ENDED的拖动事件给应用程序中的所有拖动事件监听器。这用来表示拖动操作结束了。 每个监听器应当如下做: 1.如果操作期间监听器改变了view对象的外观,应当重置为默认外观。这是给用户一个可视的表示操作结束了。 2.监听器可选择的调用getResult()来找出操作的更多信息。如果监听器返回true来响应ACTION_DROP,getResult()返回true.其他情况下getResult()返回false,包括系统没有发出ACTION_DROP事件的情况。 3.监听器应当返回true给系统。

出门走好路,出口说好话,出手做好事。

android 拖放模型

相关文章:

你感兴趣的文章:

标签云: