zoukankan      html  css  js  c++  java
  • Android开发之Drag&Drop框架实现拖放手势

      Android3.0提供了drag/drop框架,利用此框架可以实现使用拖放手势将一个view拖放到当前布局中的另外一个view中。本文将介绍如何使用拖放框架。

    一、实现拖放的步骤

       首先,我们先了解一下拖放过程,从官方文档可以知道,整个拖放过程共分为4个步骤,具体如下:

      1、  Started:启动拖放,主要是调用被拖放View的startDrag方法。此方法原型为:

    public final boolean startDrag(ClipData data,

                    View.DragShadowBuilder shadowBuilder,

                    Object myLocalState,

                    int flags)

      启动后,系统生成拖放阴影并发送action为ACTION_DRAG_STARTED的拖放事件到当前布局中已经设置了拖放监听的View。

      2、  Continuing:保持拖动状态。在此过程中系统可能会发送一个或多个拖动事件给设置了拖放监听器的View,比如ACTION_DRAG_ENTEREDACTION_DRAG_LOCATION等。

      3、  Dropped:用户在目标区域内释放拖动阴影,系统会向设置了拖放监听器的View发送action为ACTION_DROP的事件。

      4、  Ended:用户释放了拖动阴影,系统会向设置了拖放监听器的View发送action为ACTION_DRAG_ENDED事件,完成拖放。

    二、拖放过程中关键的接口和类

       其次,我们要了解清楚拖放过程中的几个关键的接口和类,主要有OnDragListener、DragEvent、DragShadowBuilder、ClipData、ClipDescription等。

      1、OnDragListener:接口,拖放事件监听器。当发生Drag时,回调此接口中的方法。接口中只含有一个方法onDrag,方法原型为:

       boolean onDrag(View v, DragEvent event)

       参数v:设置了监听器的View

       参数event:拖放事件的参数,封装了拖放相关的数据

       返回值:true-事件已处理;false事件未处理。

      2、DragEvent:拖放事件对象,根据action的不同,包含不同的事件数据。

      3、DragShadowBuilder:拖放阴影构造者对象,用于构造拖放阴影。

      4、ClipData、ClipDescription:用于拖放的移动数据。

    三、案例展示

       对以上内容有了基本了解后,我们来进行如下案例,首先看效果图

      如图界面内共有两个区域,灰色区域和黄色区域,图标可在灰色区域内自由拖动,并可改变自己的位置,如下图

     

      当图标进入或离开黄色区域时,将改变颜色,效果图如下

    四、案例实现

       下面我们看看具体如何实现:

      布局文件,代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/topContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <ImageView
            android:id="@+id/img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="@null"
            android:src="@drawable/ic_launcher" />
    
        <LinearLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:layout_alignParentBottom="true"
            android:orientation="vertical"
            android:background="#cccccc" >
            <TextView
                android:id="@+id/title"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:textColor="#ff0000"
                android:textSize="18sp" />
        </LinearLayout>
    
    </RelativeLayout>

      Java文件:

      为ImageView绑定长点击事件

    imageView.setOnLongClickListener(new OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    //创建移动数据
                    ClipData.Item item = new ClipData.Item((String) v.getTag());
                    ClipData data = new ClipData(IMAGEVIEW_TAG,
                            new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN },
                            item);
                    //调用startDrag方法,第二个参数为创建拖放阴影
                    v.startDrag(data, new View.DragShadowBuilder(v), null, 0);
                    return true;
                }
            });

      为目标View绑定拖拽监听:

    container.setOnDragListener(new OnDragListener() {
                @Override
                public boolean onDrag(View v, DragEvent event) {
                    final int action = event.getAction();
                    switch (action) {
                    case DragEvent.ACTION_DRAG_STARTED:
                        //拖拽开始事件
                        if (event.getClipDescription().hasMimeType(
                                ClipDescription.MIMETYPE_TEXT_PLAIN)) {
                            return true;
                        }
                        return false;
                    case DragEvent.ACTION_DRAG_ENTERED:
                        //被拖放View进入目标View
                        container.setBackgroundColor(Color.YELLOW);
                        return true;
                    case DragEvent.ACTION_DRAG_LOCATION:
                        return true;
                    case DragEvent.ACTION_DRAG_EXITED:
                        //被拖放View离开目标View
                        container.setBackgroundColor(Color.BLUE);
                        title.setText("");
                        return true;
                    case DragEvent.ACTION_DROP:
                        //释放拖放阴影,并获取移动数据
                        ClipData.Item item = event.getClipData().getItemAt(0);
                        String dragData = item.getText().toString();
                        title.setText(dragData+event.getY()+":"+event.getX());
                        return true;
                    case DragEvent.ACTION_DRAG_ENDED:
                        //拖放事件完成
                        return true;
                    default:
                        break;
                    }
                    return false;
                }
            });
    五、源码下载

      想要动手实践的小伙伴,可以点击“源码下载”下载完整工程测试。

    作者:杰瑞教育
    出处:http://www.cnblogs.com/jerehedu/ 
    本文版权归烟台杰瑞教育科技有限公司和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
     
  • 相关阅读:
    vue-cli3项目引用zepto报$不存在怎么处理
    RocketMQ(五):server端处理框架及消费数据查找实现
    文件上传踩坑记及文件清理原理探究
    ES使用总结 --ES实践速查手册
    java 执行shell命令及日志收集避坑指南
    Hive 如何快速拉取大批量数据
    程序员表白程序,哈哈哈,笑死我了
    发现了一个好玩的辞职程序,哈哈哈,笑死我了
    为什么最新版的VS2017没有net framework 4.6.2,net framework 4.7.2,net framework 4.6.2,net framework 4.8,也无法安装
    各个版本 Windows 10 的名称、完整版本号、开发代号和系统自带的 .NET Framework 版本
  • 原文地址:https://www.cnblogs.com/jerehedu/p/4427588.html
Copyright © 2011-2022 走看看