设计拖放操作

本节主要内容如下:

1.  如何开始拖拽;

2.  在拖拽期间如何响应事件;

3.  如何响应落下事件;

4.  如何结束拖放操作。

开始拖拽

用户使用一个拖拽手势开始拖拽,通常是在View对象上长按。在响应中,应该做下列事情:

1.  必要时,给要移动的数据创建一个ClipData和ClipData.Item对象,作为ClipData对象的一部分,在ClipData对象内部的ClipDescription对象中保存了元数据。因为拖放操作不代表数据的移动,因此可以使用null来代替实际的对象。

例如,以下代码段显示了如何在ImageView对象的长按事件上创建一个包含ImageView对象标签的ClipData对象。

// Create a string for the ImageView label
private
static final
String IMAGEVIEW_TAG =
"icon bitmap"

// Creates a new ImageView
ImageView imageView
= new ImageView(this);

// Sets the bitmap for the ImageView from an icon bit map (defined elsewhere)
imageView.setImageBitmap(mIconBitmap);

// Sets the tag
imageView.setTag(IMAGEVIEW_TAG);

...

// Sets a long click listener for the ImageView using an anonymous listener object that
// implements the OnLongClickListener interface
imageView.setOnLongClickListener(newView.OnLongClickListener(){

// Defines the one method for the interface, which is called when the View is long-clicked
    publicboolean onLongClick(View v){

// Create a new ClipData.
    // This is done in two steps to provide clarity. The convenience method
    // ClipData.newPlainText() can create a plain text ClipData in one step.

// Create a new ClipData.Item from the ImageView object's tag
    ClipData.Item item=
new ClipData.Item(v.getTag());

// Create a new ClipData using the tag as a label, the plain text MIME type, and
    // the already-created item. This will create a new ClipDescription object within the
    // ClipData, and set its MIME type entry to "text/plain"
    ClipData dragData=
new ClipData(v.getTag(),ClipData.MIMETYPE_TEXT_PLAIN,item);

// Instantiates the drag shadow builder.
    View.DrawShadowBuilder myShadow=
new MyDragShadowBuilder(imageView);

// Starts the drag

v.startDrag(dragData,  // the data to be dragged
                        myShadow,  // the drag shadow builder
                        null,      // no need to use local data
                        0          // flags (not currently used, set to 0)
            );

}

}

2. 以下代码段定义了一个myDragShadowBuilder类,它创建一个用于拖拽TextView对象的小的灰色的矩形作为拖拽影子:

private
static class
MyDragShadowBuilder extends
View.DragShadowBuilder{

// The drag shadow image, defined as a drawable thing
    privatestatic
Drawable shadow;

// Defines the constructor for myDragShadowBuilder
        publicMyDragShadowBuilder(View v){

// Stores the View parameter passed to myDragShadowBuilder.
            super(v);

// Creates a draggable image that will fill the Canvas provided by the system.
            shadow =new
ColorDrawable(Color.LTGRAY);
        }

// Defines a callback that sends the drag shadow dimensions and touch point back to the
        // system.
        @Override
        publicvoid onProvideShadowMetrics
(Point size,Point touch)
            // Defines local variables
            privateint width, height;

// Sets the width of the shadow to half the width of the original View
            width = getView().getWidth()/
2;

// Sets the height of the shadow to half the height of the original View
            height = getView().getHeight()/
2;

// The drag shadow is a ColorDrawable. This sets its dimensions to be the same as the
            // Canvas that the system will provide. As a result, the drag shadow will fill the
            // Canvas.
            shadow.setBounds(0,0,
width, height);

// Sets the size parameter's width and height values. These get back to the system
            // through the size parameter.
            size.set(width, height);

// Sets the touch point's position to be in the middle of the drag shadow
            touch.set(width/
2, height/
2);
        }

// Defines a callback that draws the drag shadow in a Canvas that the system constructs
        // from the dimensions passed in onProvideShadowMetrics().
        @Override
        publicvoid onDrawShadow(Canvas canvas){

// Draws the ColorDrawable in the Canvas passed in from the system.
            shadow.draw(canvas);

}

}

注意:不必扩展View.DragShadowBuilder类,因为构造器View.DragShadowBuilder(View)会创建一个默认的跟传递给它的View对象相同尺寸的拖拽影子,而且触点在拖拽影子的中心。

对拖拽开始的响应

在拖拽操作期间,系统会分发拖拽事件给当前布局中View对象的拖拽事件监听器。监听器应该通过调用getAction()方法对获得的操作类型做出反应。在拖拽开始时,这个方法返回ACTION_DRAG_STARTED.

在对ACTION_DRAG_STARTED操作类型做出的响应中,监听器应该做下列事情:

1.  调用getClipDescription()方法来获得ClipDescription对象,使用ClipDescription对象中的MIME类型方法来判断监听器是否能够接收被拖拽的数据。

如果拖拽操作不代表要移动的数据,这个判断就不是必须的了。

2.  如果监听器能够接受落下事件,它应该返回true。这样就告诉系统可以继续给这个监听器发送拖拽事件。如果不能够接收落下事件,它应该返回false,系统就不再会给这个监听器发送拖拽事件了。

要注意的是针对ACTION_DRAG_STARTED事件,下列DragEvent对象方法不能获取有效的数据:getClipData()、getX()、getY()和getResult()。

在拖拽期间处理事件

在拖拽期间,在响应ACTION_DARG_STARTED拖拽事件中返回true的监听器会继续接收拖拽事件。这种类型的拖拽监听器会依赖拖拽期间拖拽影子的位置和监听器的View对象的可见性来接收拖拽事件。

在拖拽期间,监听器主要使用拖拽事件来判断是否应该改变View对象的外观。

拖拽期间,getAction方法会返回下列三个值之一:

1. ACTION_DRAG_ENTERED:当触点(触屏上手指下方的点)进入监听器View对象的边框时,View对象的拖拽监听器就会收到这个事件。

2. ACTION_DRAG_LOCATION:一旦拖拽监听器收到一个ACTION_DRAG_ENTERED事件,并且在收到ACTION_DRAG_EXITED事件之前,每次移动触点时都会收到一个新的ACTION_DRAG_LOCATION事件。getX和getY()方法会返回触点的X和Y轴坐标。

3. ACTION_DRAG_EXITED:在拖拽影子离开监听器View对象的边框之后,这个事件会发送给之前收到ACTION_DRAG_ENTERED事件的那个监听器。

监听器不需要对这些操作类型都做出反应,如果监听器给系统返回了一个值,它就会被忽略。以下是响应这些操作类型的一些指南:

1.  在对ACTION_DRAG_ENTERED或ACTION_DRAG_LOCATION事件的响应中,监听器能够改变View对象的外观来指示View对象能够接受放下事件。

2. ACTION_DRAG_LOCATION事件包含了对getX()和getY()方法有效的数据,这两个方法的返回值对应了触点的位置。监听器可以使用这个信息来修改触点所在的View对象的外观,也能使用这个信息来判断用户拖放阴影的准确位置。

3. 在对ACTION_DRAG_EXITED事件的响应中,监听器应该重设在响应ACTION_DRAG_ENTERED或ACTION_DRAG_LOCATION事件对外观的任何改变。这个事件指示拖放对象已经离开准备放下的目标。

响应放下事件

当用户在应用中的一个View对象上释放了拖拽影子,并且这个View对象是之前报告的能够接收被拖拽内容的那个View对象,系统就会给这个View对象发送一个ACTION_DROP类型的拖拽事件。监听器应该做下列事情:

1.  调用getClipData()方法获得ClipData对象,这个对象在调用startDrag()方法时被初始化并保存在拖拽监听器中。如果拖放操作不移动数据,那么就不需要做这件事;

2.  返回true,指示放下事件被成功处理,否则返回false。对于ACTION_DRAG_ENDED事件,这个返回值就是通过getResult()方法返回的值。

要注意的是,如果系统不发送ACTION_DROP事件,针对对ACTION_DRAG_ENDED事件的getResult()方法调用的返回值是false。

系统允许用户在监听器不接收拖放事件的View对象之上释放拖拽影子,也允许用户在应用程序UI的空白区域或应用程序以外的区域释放拖拽影子,这样系统就不会发出ACTION_DROP类型的事件,直接会发出一个ACTION_DRAG_ENDED事件。

响应拖拽结束事件

用户释放了拖拽影子后,系统会立即给应用程序中所有的拖拽事件监听器发送ACTION_DRAG_ENDED类型的拖拽事件,指示拖拽操作结束了。

每个监听器都应该做下列事情:

1.  如果监听器在操作期间改变了View对象的外观,那么应该把View对象重设为默认的外观。这是对用户可见的操作结束的指示;

2.  监听器能够可选的调用getResult()方法来查找更多的相关操作。如果在响应ACTION_DROP类型的事件中监听器返回了true,那么getResult()方法也会返回true。在其他的情况中,getResult()方法会返回false,包括系统没有发出ACTION_DROP事件的情况;

3.  监听器应该给系统返回true。

响应拖拽事件的一个例子:

所有的拖拽事件都会被拖拽事件的回调方法或监听器接收。以下代码片段是一个简单的在监听器中对拖拽事件作出反应的示例。

// Creates a new drag event listener
mDragListen =new myDragEventListener();

View imageView=
new ImageView(this);

// Sets the drag event listener for the View
imageView.setOnDragListener(mDragListen);

...

protectedclass myDragEventListener
implements View.OnDragEventListener{

// This is the method that the system calls when it dispatches a drag event to the
    // listener.
    publicboolean onDrag(View
v,DragEvent
event){

// Defines a variable to store the action type for the incoming event
        finalint action
=event.getAction();

// Handles each of the expected events
        switch(action){

caseDragEvent.ACTION_DRAG_STARTED:

// Determines if this View can accept the dragged data
               
if(event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)){

// As an example of what your application might do,
                   
// applies a blue color tint to the View to indicate that it can accept
                   
// data.
                    v.setColorFilter(Color.BLUE);

// Invalidate the view to force a redraw in the new tint
                    v.invalidate();

// returns true to indicate that the View can accept the dragged data.
                   
return(true);

}else
{

// Returns false. During the current drag and drop operation, this View will
                   
// not receive events again until ACTION_DRAG_ENDED is sent.
                   
return(false);

}
               
break;

caseDragEvent.ACTION_DRAG_ENTERED:{

// Applies a green tint to the View. Return true; the return value is ignored.

v.setColorFilter(Color.GREEN);

// Invalidate the view to force a redraw in the new tint
                v.invalidate();

return(true);

break;

caseDragEvent.ACTION_DRAG_LOCATION:

// Ignore the event
                   
return(true);

break;

caseDragEvent.ACTION_DRAG_EXITED:

// Re-sets the color tint to blue. Returns true; the return value is ignored.
                    v.setColorFilter(Color.BLUE);

// Invalidate the view to force a redraw in the new tint
                    v.invalidate();

return(true);

break;

caseDragEvent.ACTION_DROP:

// Gets the item containing the dragged data
                   
ClipData.Item item=
event.getClipData().getItemAt(0);

// Gets the text data from the item.
                    dragData= item.getText();

// Displays a message containing the dragged data.
                   
Toast.makeText(this,"Dragged
data is " + dragData,
Toast.LENGTH_LONG);

// Turns off any color tints
                    v.clearColorFilter();

// Invalidates the view to force a redraw
                    v.invalidate();

// Returns true. DragEvent.getResult() will return true.
                   
return(true);

break;

caseDragEvent.ACTION_DRAG_ENDED:

// Turns off any color tinting
                    v.clearColorFilter();

// Invalidates the view to force a redraw
                    v.invalidate();

// Does a getResult(), and displays what happened.
                   
if(event.getResult()){
                       Toast.makeText(this,"The
drop was handled.",Toast.LENGTH_LONG);

}else
{
                       Toast.makeText(this,"The
drop didn't work.",Toast.LENGTH_LONG);

};

// returns true; the value is ignored.
                   
return(true);

break;

// An unknown action type was received.
               
default:
                   
Log.e("DragDrop Example","Unknown
action type received by OnDragListener.");

break;
        };

};

};

 
 

Android 用户界面---拖放(Drag and Drop)(三)的更多相关文章

  1. Android开发者指南-用户界面-拖放-Drag and Drop[原创译文]

      英文原文:http://developer.android.com/guide/topics/ui/drag-drop.html 版本:Android 4.0 r1 译者注:黄色底色为未决译文 快 ...

  2. Android 用户界面---拖放(Drag and Drop)(二)

      拖拽事件监听器和回调方法 View对象既可以用实现View.OnDragListener接口的拖放事件监听器,也可以用View对象的onDragEvent(DragEvent)回调方法来接收拖拽事 ...

  3. Android 用户界面---拖放(Drag and Drop)(一)

    用Android的拖放框架,能够允许用户使用图形化的拖放手势,把数据从当前布局中的一个View对象中移到另一个View对象中.这个框架包括:拖拽事件类.拖拽监听器.以及辅助的方法和类. 尽管这个框架主 ...

  4. HTML5 之拖放(drag与drop)

    拖放(Drag 和 drop)是 HTML5 标准的组成部分. 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. HTML5 拖放实例 ...

  5. HTML5 拖放---drag和drop

    拖放四步走:第一步:设置元素可拖放,即把 draggable属性设置为 true:  例:<div id="div" draggable="true"&g ...

  6. 拖放(Drag和Drop)--html5

    拖放,就是抓取一个对象后拖放到另一个位置.很常用的一个功能,在还没有html5的时候,我们实现这个功能,通常会用大量的js代码,再利用mousemove,mouseup等鼠标事件来实现,总的来说比较麻 ...

  7. HTML 5 拖放(Drag 和drop)

    浏览器支持 Internet Explorer 9.Firefox.Opera 12.Chrome 以及 Safari 5. 1.把标签 draggable 属性设置为 true. 2.向标签添加on ...

  8. 在Blazor中实现拖放(drag and drop)

    前言 我在实现一个含有待办列表功能的页面时,发现了一个好看的设计,它将待办分为--"待办","正在进行",和"已完成"三种状态,并且将待办通 ...

  9. HTML5 拖放(Drag 和 Drop)功能开发——基础实战

    随着HTML5的普及度越来越高,现在写代码也遇到一些了,经过同事的点播开展了一次Dojo活动用以技术交流,我也乘此机会将HTML5的拖放功能整理了一下. 简介 拖拽(Drag/Drop)是个非常普遍的 ...

随机推荐

  1. AngularJs学习笔记--Forms

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/forms 控件(input.select.textarea)是用户输入数据的一种方式.Form(表单) ...

  2. sao/jsp

    sao/i18n/message/ Messages-Client.xml   Messages-Server.xml   sao/wsdl Verification.wsdl   IProcessS ...

  3. Request/Server的相关topic

    Request---------Server模式 HTTP 协议--------->这个可能返回json, 也可能是HTML HTML页面处理的流程以及资源文件的加载 浏览器最大连接数 js资源 ...

  4. CSS 类名的单词连字符:下划线还是连接符?

    本文的部分内容整理自我对此问题的解答: 命名 CSS 的类或 ID 时单词间如何连接? - 知乎 问题 CSS 类或 ID 命名时单词间连接通常有这几种写法: 驼峰式: solutionTitle.s ...

  5. Sqli-labs less 42

    Less-42 Update更新数据后,经过mysql_real_escape_string()处理后的数据,存入到数据库当中后不会发生变化.在select调用的时候才能发挥作用.所以不用考虑在更新密 ...

  6. POJ 1742

    Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 27580   Accepted: 9335 Descriptio ...

  7. Android——横屏和竖屏的切换,以及明文密码的显示

    查看API文档: android.content.pm.ActivityInfo    在手机的使用中,我们要根据不同的需求来改变屏幕的显示方向,一般在浏览信息时是竖屏,在玩游戏的时候就要切换到横屏. ...

  8. Android开发者应该深入学习的10个开源应用项目

    Android 开发带来新一轮热潮让很多移动开发者都投入到这个浪潮中去了,创造了许许多多相当优秀的应用.其中也有许许多多的开发者提供了应用开源项目,贡献出他们的 智慧和创造力.学习开源代码是掌握技术的 ...

  9. 使用Ninject来解决程序中组件的耦合问题

    1.为什么要用Ninject? Ninject是一个IOC容器用来解决程序中组件的耦合问题,它的目的在于做到最少配置.其他的的IOC工具过于依赖配置文件,需要使用assembly-qualified名 ...

  10. hdu 4027 Can you answer these queries? 线段树

    线段树+剪枝优化!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> #includ ...