Android:Drag and Drop的应用

最近看了下Drag and Drop部分的原文,觉得很有意思就像自己试着做一下,说实在的原文真的是不好读啊,要感谢那些为我们发表译文的大神们,

真的是不容易,原文中给了例子,但是只有后面零星的代码,真的是不知道怎么用,索性就搜了下原文翻译,顺便看看有没有人实现出一个例子什

么的,只可惜译文多得很就是没人做出一个可以参照的例子,无奈自己就根据文章意思改了改代码,终于是能用了,但是不知道用的对不对,在这

分享一下,也想看看有没有懂的大神给指点指点。

我的理解就是有一个图片通过监听长期的点击事件得到一个拖拽阴影(也不知道是不是这么叫的),将其拖动到指定的区域,然后在区域里加

监听来判断拖拽的位置是否在区域内,然后在判断释放的位置来断定是否接收到传过来的指定信息。

下面上主代码,MainActivity.java

[java] view plaincopyprint?

  1. import android.annotation.SuppressLint;
  2. import android.app.Activity;
  3. import android.content.ClipData;
  4. import android.content.ClipDescription;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Point;
  8. import android.graphics.drawable.ColorDrawable;
  9. import android.graphics.drawable.Drawable;
  10. import android.os.Bundle;
  11. import android.util.Log;
  12. import android.view.DragEvent;
  13. import android.view.View;
  14. import android.view.View.OnDragListener;
  15. import android.view.View.OnLongClickListener;
  16. import android.widget.ImageView;
  17. import android.widget.TextView;
  18. import android.widget.Toast;
  19. public class MainActivity extends Activity {
  20. /**
  21. * 为ImageView创建一个字符标签
  22. */
  23. private static final String IMAGEVIEW_TAG = "icon bitmap";
  24. /**
  25. * 创建用于拖动的ImageView
  26. */
  27. private ImageView imageView;
  28. /**
  29. * 拖动事件监听
  30. */
  31. private myDragEventListener mDragListen;
  32. /**
  33. * 拖动ImageView的长按事件监听
  34. */
  35. private OnLongClickListener mLongClick = new OnLongClickListener() {
  36. @SuppressLint("NewApi")
  37. @Override
  38. public boolean onLongClick(View v) {
  39. // 创建一个ClipData对象
  40. // 这里分为两步,第一步中方法ClipData.newPlainText()可以创建一个纯文本ClipData
  41. // 根据ImageView的标签创建一个ClipData.Item对象
  42. ClipData.Item item = new ClipData.Item((CharSequence) v.getTag());
  43. // 使用标签,纯文本和已经创建的item来创建一个ClipData对象
  44. // 这里将在ClipData中创建一个新的ClipDescription对象并设置它的MIME类型为"text/plain"
  45. ClipData dragData = new ClipData((CharSequence) v.getTag(),
  46. new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN }, item);
  47. // 实例化拖拽影子.
  48. View.DragShadowBuilder myShadow = new MyDragShadowBuilder(imageView);
  49. // 开始拖拽
  50. return v.startDrag(dragData, // 被拖拽的数据
  51. myShadow, // 拖拽的影子
  52. null, // 不需要使用本地数据
  53. 0 // 标记(目前用不到,设置为0)
  54. );
  55. }
  56. };
  57. @Override
  58. protected void onCreate(Bundle savedInstanceState) {
  59. super.onCreate(savedInstanceState);
  60. setContentView(R.layout.activity_main);
  61. init();
  62. }
  63. /**
  64. * 功能描述: 初始化<br>
  65. */
  66. public void init() {
  67. imageView = new ImageView(this);
  68. imageView = (ImageView) findViewById(R.id.drag_image);
  69. // 设置标签
  70. imageView.setTag(IMAGEVIEW_TAG);
  71. //添加长按事件
  72. imageView.setOnLongClickListener(mLongClick);
  73. // 创建一个拖拽的事件监听器
  74. mDragListen = new myDragEventListener();
  75. // 拖拽反应区域
  76. View view = findViewById(R.id.drag_room);
  77. // 为该区域添加拖动事件监听器
  78. view.setOnDragListener(mDragListen);
  79. }
  80. /**
  81. * 〈拖动阴影〉<br>
  82. */
  83. @SuppressLint("NewApi")
  84. private static class MyDragShadowBuilder extends View.DragShadowBuilder {
  85. // 拖动阴影的图像, 作为一个drawable来定义
  86. private static Drawable shadow;
  87. // 构造函数
  88. public MyDragShadowBuilder(View v) {
  89. // 通过myDragShadowBuilder存储View参数
  90. super(v);
  91. // 创建一个可拖拽的图像,此图像可以通过系统的Canvas来填充
  92. shadow = new ColorDrawable(Color.LTGRAY);
  93. }
  94. // 定义一个回调方法,将阴影的维度和触摸点返回给系统
  95. @Override
  96. public void onProvideShadowMetrics(Point size, Point touch) {
  97. // 定义当地的变量
  98. int width;
  99. int height;
  100. // 设置阴影的宽度为视图一半
  101. width = getView().getWidth() / 2;
  102. // 设置阴影的高度为视图一半
  103. height = getView().getHeight() / 2;
  104. // 拖拽阴影是一个ColorDrawable. 这个集合的维度和系统所提供的Canvas是一样的
  105. // 因此,拖拽阴影将会被Canvas覆盖
  106. shadow.setBounds(0, 0, width, height);
  107. // 设置参数宽度和高度的大小.通过大小参数返回给系统
  108. size.set(width, height);
  109. // 设置触摸点的位置为拖拽阴影的中心
  110. touch.set(width / 2, height / 2);
  111. }
  112. // 在画布Canvas中定义一个回调函数来绘制拖拽的阴影,该画布是通过方法onProvideShadowMetrics()提供的维度
  113. // 由系统构造
  114. @Override
  115. public void onDrawShadow(Canvas canvas) {
  116. // 在由系统传递的Canvas上绘制ColorDrawable
  117. shadow.draw(canvas);
  118. }
  119. }
  120. @SuppressLint("NewApi")
  121. protected class myDragEventListener implements OnDragListener {
  122. // 该方法由系统调用,当有拖拽事件发生时
  123. @SuppressLint("ShowToast")
  124. public boolean onDrag(View v, DragEvent event) {
  125. // 定义一个变量来存储通过事件传递的action类型
  126. final int action = event.getAction();
  127. // 每个事件的处理
  128. switch (action) {
  129. case DragEvent.ACTION_DRAG_STARTED:
  130. System.out.println("ACTION_DRAG_STARTED----------------");
  131. // 确定是否这个视图(View)可以接收拖拽的数据类型
  132. if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
  133. // 这里是一个例子,通过更改TextView的背景颜色和文字
  134. // 来证明它可以接收数据
  135. v.setBackgroundColor(Color.BLUE);
  136. ((TextView) v).setText("drag");
  137. // 强制重绘视图以显示新的特性
  138. v.invalidate();
  139. // 通过返回true来表明View可以接收拖拽数据
  140. return (true);
  141. } else {
  142. // 返回false. 在当前是拖拽和落下操作时,视图(View)将不再接收
  143. // 事件直到发送ACTION_DRAG_ENDED
  144. return (false);
  145. }
  146. case DragEvent.ACTION_DRAG_ENTERED:
  147. System.out.println("ACTION_DRAG_ENTERED----------------");
  148. // 拖拽的阴影已经到达指定的区域,TextView背景变为绿色,返回true,该返回值没有意义
  149. v.setBackgroundColor(Color.GREEN);
  150. ((TextView) v).setText("in");
  151. // 强制重绘视图以显示新的特性
  152. v.invalidate();
  153. return (true);
  154. case DragEvent.ACTION_DRAG_LOCATION:
  155. // 忽略该事件
  156. return (true);
  157. case DragEvent.ACTION_DRAG_EXITED:
  158. System.out.println("ACTION_DRAG_EXITED----------------");
  159. // 拖拽阴影超出制定区域,重置TextView背景色为蓝色
  160. v.setBackgroundColor(Color.BLUE);
  161. ((TextView) v).setText("drag");
  162. // 强制重绘视图以显示新的特性
  163. v.invalidate();
  164. return (true);
  165. case DragEvent.ACTION_DROP:
  166. System.out.println("ACTION_DROP----------------");
  167. // 获得item包括拖拽数据
  168. ClipData.Item item = event.getClipData().getItemAt(0);
  169. // 从item获得文本数据
  170. CharSequence dragData = item.getText();
  171. // 显示拖拽数据中包含的信息.
  172. Toast.makeText(MainActivity.this, "Dragged data is: " + dragData, Toast.LENGTH_SHORT).show();
  173. // 重新设置颜色和文字
  174. v.setBackgroundColor(Color.WHITE);
  175. ((TextView) v).setText("get");
  176. // 强制重绘视图以显示新的特性
  177. v.invalidate();
  178. // 返回true. DragEvent.getResult()将会返回true.
  179. return (true);
  180. case DragEvent.ACTION_DRAG_ENDED:
  181. System.out.println("ACTION_DRAG_ENDED----------------");
  182. // 重新设置颜色和文字
  183. v.setBackgroundColor(Color.WHITE);
  184. ((TextView) v).setText("room");
  185. // 强制重绘视图以显示新的特性
  186. v.invalidate();
  187. //通过getResult()方法的返回值判断发生了什么
  188. if (event.getResult()) {
  189. Toast.makeText(MainActivity.this, "The drop was handled.", Toast.LENGTH_LONG).show();
  190. } else {
  191. Toast.makeText(MainActivity.this, "The drop didn‘t work.", Toast.LENGTH_LONG).show();
  192. };
  193. return (true);
  194. // 其他未知的action.
  195. default:
  196. Log.e("DragDrop Example", "Unknown action type received by OnDragListener.");
  197. break;
  198. }
  199. ;
  200. return true;
  201. };
  202. }
  203. }
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.view.View.OnLongClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
    /**
     * 为ImageView创建一个字符标签
     */
    private static final String IMAGEVIEW_TAG = "icon bitmap";
    /**
     * 创建用于拖动的ImageView
     */
    private ImageView imageView;
    /**
     * 拖动事件监听
     */
    private myDragEventListener mDragListen;
    /**
     * 拖动ImageView的长按事件监听
     */
    private OnLongClickListener mLongClick = new OnLongClickListener() {

        @SuppressLint("NewApi")
        @Override
        public boolean onLongClick(View v) {
            // 创建一个ClipData对象
            // 这里分为两步,第一步中方法ClipData.newPlainText()可以创建一个纯文本ClipData

            // 根据ImageView的标签创建一个ClipData.Item对象
            ClipData.Item item = new ClipData.Item((CharSequence) v.getTag());

            // 使用标签,纯文本和已经创建的item来创建一个ClipData对象
            // 这里将在ClipData中创建一个新的ClipDescription对象并设置它的MIME类型为"text/plain"
            ClipData dragData = new ClipData((CharSequence) v.getTag(),
                    new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN }, item);

            // 实例化拖拽影子.
            View.DragShadowBuilder myShadow = new MyDragShadowBuilder(imageView);

            // 开始拖拽

            return v.startDrag(dragData, // 被拖拽的数据
                    myShadow, // 拖拽的影子
                    null, // 不需要使用本地数据
                    0 // 标记(目前用不到,设置为0)
            );
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();
    }
    /**
     * 功能描述: 初始化<br>
     */
    public void init() {
        imageView = new ImageView(this);
        imageView = (ImageView) findViewById(R.id.drag_image);
        // 设置标签
        imageView.setTag(IMAGEVIEW_TAG);
        //添加长按事件
        imageView.setOnLongClickListener(mLongClick);
        // 创建一个拖拽的事件监听器
        mDragListen = new myDragEventListener();
        // 拖拽反应区域
        View view = findViewById(R.id.drag_room);
        // 为该区域添加拖动事件监听器
        view.setOnDragListener(mDragListen);
    }
    /**
     * 〈拖动阴影〉<br>
     */
    @SuppressLint("NewApi")
    private static class MyDragShadowBuilder extends View.DragShadowBuilder {
        // 拖动阴影的图像, 作为一个drawable来定义
        private static Drawable shadow;
        // 构造函数
        public MyDragShadowBuilder(View v) {
            // 通过myDragShadowBuilder存储View参数
            super(v);
            // 创建一个可拖拽的图像,此图像可以通过系统的Canvas来填充
            shadow = new ColorDrawable(Color.LTGRAY);
        }

        // 定义一个回调方法,将阴影的维度和触摸点返回给系统
        @Override
        public void onProvideShadowMetrics(Point size, Point touch) {
            // 定义当地的变量
            int width;
            int height;
            // 设置阴影的宽度为视图一半
            width = getView().getWidth() / 2;
            // 设置阴影的高度为视图一半
            height = getView().getHeight() / 2;
            // 拖拽阴影是一个ColorDrawable. 这个集合的维度和系统所提供的Canvas是一样的
            // 因此,拖拽阴影将会被Canvas覆盖
            shadow.setBounds(0, 0, width, height);
            // 设置参数宽度和高度的大小.通过大小参数返回给系统
            size.set(width, height);
            // 设置触摸点的位置为拖拽阴影的中心
            touch.set(width / 2, height / 2);
        }

        // 在画布Canvas中定义一个回调函数来绘制拖拽的阴影,该画布是通过方法onProvideShadowMetrics()提供的维度
        // 由系统构造
        @Override
        public void onDrawShadow(Canvas canvas) {
            // 在由系统传递的Canvas上绘制ColorDrawable
            shadow.draw(canvas);
        }
    }

    @SuppressLint("NewApi")
    protected class myDragEventListener implements OnDragListener {

        // 该方法由系统调用,当有拖拽事件发生时
        @SuppressLint("ShowToast")
        public boolean onDrag(View v, DragEvent event) {
            // 定义一个变量来存储通过事件传递的action类型
            final int action = event.getAction();
            // 每个事件的处理
            switch (action) {

                case DragEvent.ACTION_DRAG_STARTED:
                    System.out.println("ACTION_DRAG_STARTED----------------");
                    // 确定是否这个视图(View)可以接收拖拽的数据类型
                    if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
                        // 这里是一个例子,通过更改TextView的背景颜色和文字
                        // 来证明它可以接收数据
                        v.setBackgroundColor(Color.BLUE);
                        ((TextView) v).setText("drag");
                        // 强制重绘视图以显示新的特性
                        v.invalidate();
                        // 通过返回true来表明View可以接收拖拽数据
                        return (true);

                    } else {
                        // 返回false. 在当前是拖拽和落下操作时,视图(View)将不再接收
                        // 事件直到发送ACTION_DRAG_ENDED
                        return (false);
                    }

                case DragEvent.ACTION_DRAG_ENTERED:
                    System.out.println("ACTION_DRAG_ENTERED----------------");
                    // 拖拽的阴影已经到达指定的区域,TextView背景变为绿色,返回true,该返回值没有意义
                    v.setBackgroundColor(Color.GREEN);
                    ((TextView) v).setText("in");
                    // 强制重绘视图以显示新的特性
                    v.invalidate();
                    return (true);

                case DragEvent.ACTION_DRAG_LOCATION:
                    // 忽略该事件
                    return (true);

                case DragEvent.ACTION_DRAG_EXITED:
                    System.out.println("ACTION_DRAG_EXITED----------------");
                    // 拖拽阴影超出制定区域,重置TextView背景色为蓝色
                    v.setBackgroundColor(Color.BLUE);
                    ((TextView) v).setText("drag");
                    // 强制重绘视图以显示新的特性
                    v.invalidate();
                    return (true);

                case DragEvent.ACTION_DROP:
                    System.out.println("ACTION_DROP----------------");
                    // 获得item包括拖拽数据
                    ClipData.Item item = event.getClipData().getItemAt(0);
                    // 从item获得文本数据
                    CharSequence dragData = item.getText();
                    // 显示拖拽数据中包含的信息.
                    Toast.makeText(MainActivity.this, "Dragged data is: " + dragData, Toast.LENGTH_SHORT).show();
                    // 重新设置颜色和文字
                    v.setBackgroundColor(Color.WHITE);
                    ((TextView) v).setText("get");
                    // 强制重绘视图以显示新的特性
                    v.invalidate();

                    // 返回true. DragEvent.getResult()将会返回true.
                    return (true);

                case DragEvent.ACTION_DRAG_ENDED:
                    System.out.println("ACTION_DRAG_ENDED----------------");
                    // 重新设置颜色和文字
                    v.setBackgroundColor(Color.WHITE);
                    ((TextView) v).setText("room");
                    // 强制重绘视图以显示新的特性
                    v.invalidate();
                    //通过getResult()方法的返回值判断发生了什么
                    if (event.getResult()) {
                        Toast.makeText(MainActivity.this, "The drop was handled.", Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(MainActivity.this, "The drop didn‘t work.", Toast.LENGTH_LONG).show();

                    };
                    return (true);

                    // 其他未知的action.
                default:
                    Log.e("DragDrop Example", "Unknown action type received by OnDragListener.");

                    break;
            }
            ;
            return true;
        };
    }

}

这里就是通过长按ImageView将其拖动到一个TextView的区域里来改变TextView的状态,并显示接收到的数据

布局文件就很简单了 activity_main.xml

[html] view plaincopyprint?

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="fill_parent"
  3. android:layout_height="fill_parent" >
  4. <TextView
  5. android:id="@+id/drag_room"
  6. android:layout_width="150dip"
  7. android:layout_height="150dip"
  8. android:gravity="center"
  9. android:layout_centerInParent="true"
  10. android:text="room"
  11. android:textSize="18dp"/>
  12. <ImageView
  13. android:id="@+id/drag_image"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:layout_above="@id/drag_room"
  17. android:src="@drawable/move" />
  18. </RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <TextView
        android:id="@+id/drag_room"
        android:layout_width="150dip"
        android:layout_height="150dip"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:text="room"
        android:textSize="18dp"/>

    <ImageView
        android:id="@+id/drag_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/drag_room"
        android:src="@drawable/move" />

</RelativeLayout>

基本就是这些,也不知道做的对不对,有懂的给提提吧

为了方便附上原代码,里面还有个拖动图片的例子

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 19:32:10

Android:Drag and Drop的应用的相关文章

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

Android 用户界面---拖放(Drag and Drop)(一) Android 用户界面---拖放(Drag and Drop)(二) Android 用户界面---拖放(Drag and Drop)(三)

Android 用户界面---拖放(Drag and Drop)(三)

设计拖放操作 本节主要内容如下: 1.  如何开始拖拽: 2.  在拖拽期间如何响应事件: 3.  如何响应落下事件: 4.  如何结束拖放操作. 开始拖拽 用户使用一个拖拽手势开始拖拽,通常是在View对象上长按.在响应中,应该做下列事情: 1.  必要时,给要移动的数据创建一个ClipData和ClipData.Item对象,作为ClipData对象的一部分,在ClipData对象内部的ClipDescription对象中保存了元数据.因为拖放操作不代表数据的移动,因此可以使用null来代替

原生拖拽,拖放事件(drag and drop)

原生拖拽,拖放事件(drag and drop) 拖拽,拖放事件可以通过拖拽实现数据传递,达到良好的交互效果,如:从操作系统拖拽文件实现文件选择,拖拽实现元素布局的修改. drag and drop事件流程 一个完整的drag and drop流程通常包含以下几个步骤: 设置可拖拽目标.设置属性draggable="true"实现元素的可拖拽. 监听dragstart设置拖拽数据 为拖拽操作设置反馈图标(可选) 设置允许的拖放效果,如copy,move,link 设置拖放目标,默认情况

[Javascript + rxjs] Simple drag and drop with Observables

Armed with the map and concatAll functions, we can create fairly complex interactions in a simple way. We will use Observable to create a simple drag and drop example with basic DOM elements. <!DOCTYPE html> <html> <head lang="en"

关于QListWidget的Drag和Drop用法

QListWIdget的Drag和Drop. 真是坑爹到不行... 其实很简单的.. 最后搞到好多行代码.. 真是作死的节奏............... 先上代码:<这种方法也可以实现, 但是太麻烦了...> #include "PlayerDragWidget.h" #include "PlayerLyricsListItem.h" #include <QDrag> #include <QPainter> #include &

基于HTML5的Drag and Drop生成图片Base64信息

直击现场 基于HTML5的Drag and Drop生成图片Base64信息 发表于4个月前(2014-12-19 00:58)   阅读(103) | 评论(0) 11人收藏此文章, 我要收藏 赞0 慕课网,程序员升职加薪神器,点击免费学习 摘要 HTML5的Drag and Drop是很不错的功能,网上使用例子较多如 http://html5demos.com/drag ,但这些例子大部分没实际用途,本文将搞个有点使用价值的例子,通过Drag and Drop生成图片的Base64的字符串信

drag and drop

<!DOCTYPE HTML> <html> <head> <script type="text/javascript"> function allowDrop(ev) { ev.preventDefault(); } function drag(ev) { ev.dataTransfer.setData("Text",ev.target.id); } function drop(ev) { ev.preventDef

delphi Drag and Drop sample 鼠标拖放操作实例

Drag and Drop is a common operation that makes the interface user friendly: a user can drag/drop information to controls instead of having to type etc. The following sample explains basics of drag and drop. For detailed information you should refer t

通过HTML5的Drag and Drop生成拓扑图片Base64信息

HTML5 原生的 Drag and Drop是很不错的功能,网上使用例子较多如 http://html5demos.com/drag ,但这些例子大部分没实际用途,本文将搞个有点使用价值的例子,通过Drag and Drop生成图片的Base64的字符串信息. 使用Base64方式的图片有诸多好处,可将多个图片信息整合到单个js文件避免多次http请求,可以避免WebGL例子跨域访问的安全限制无法本地文件运行等好处,当然弊端也不少例如不能有效利用浏览器图片缓存机制等.使用HT for Web的