最简单的android拖拽交换view

简单说两句背景, 最近项目需要用拖拽的操作方式切换视图块位置,实现业务需求.一开始我用recyclerView+ItemTouchHelper实现了列表和Grid列表拖拽切换item(排序),但是发现不够灵活适应业务需求,或者说满足不了需求吧,就查了下资料发现android view本身已经自带拖拽function了,包括启动拖拽,监听拖拽等,都很齐全的支持了,所以就照着这些function的文档,先实现了一个拖拽交换view的基础demo, 并且需要的代码量很小.

必须先演示下效果(500k的gif):



再贴代码, 注释很齐全了, 直接注释里讲

Activity布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.liuyihui.viewdrag.DragViewActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <!--从这开始-->
        <!--每个可拖拽的组件要放在一个容器组件里-->
        <!--容器组件-->
        <LinearLayout
            android:id="@+id/view1_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:orientation="horizontal">
            <!--可拖拽的组件-->
            <LinearLayout
                android:id="@+id/view1"
                android:layout_width="120dp"
                android:layout_height="300dp"
                android:background="@android:color/holo_green_dark"
                android:orientation="vertical">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="aaa"/>
            </LinearLayout>
        </LinearLayout>

        <!--容器组件-->
        <LinearLayout
            android:id="@+id/view2_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:orientation="horizontal">

            <!--可拖拽组件-->
            <LinearLayout
                android:id="@+id/view2"
                android:layout_width="120dp"
                android:layout_height="300dp"
                android:background="@android:color/holo_orange_dark"
                android:orientation="vertical">
            </LinearLayout>
        </LinearLayout>

        <!--容器组件-->
        <LinearLayout
            android:id="@+id/view3_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:orientation="horizontal">
            <!--可拖拽的组件-->
            <LinearLayout
                android:id="@+id/view3"
                android:layout_width="120dp"
                android:layout_height="300dp"
                android:background="@android:color/holo_blue_dark"
                android:orientation="vertical">
            </LinearLayout>
        </LinearLayout>

    </RelativeLayout>

</android.support.constraint.ConstraintLayout>

Activity:

package com.liuyihui.viewdrag;

import android.content.ClipData;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

/**
 * 拖动交换视图demo
 *
 * @author liuyihui 2018年4月19日13:18:28
 */
public class DragViewActivity extends AppCompatActivity {
    private final static String TAG = "DragViewActivity";
    /** 三个容器 */
    private LinearLayout view1_container;
    private LinearLayout view2_container;
    private LinearLayout view3_container;
    /** 三要个拖动view */
    private LinearLayout view1;
    private LinearLayout view2;
    private LinearLayout view3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drag_view);
        //三个容器
        view1_container = findViewById(R.id.view1_container);
        view2_container = findViewById(R.id.view2_container);
        view3_container = findViewById(R.id.view3_container);
        //三个可拖拽view
        view1 = findViewById(R.id.view1);
        view2 = findViewById(R.id.view2);
        view3 = findViewById(R.id.view3);

        //拖拽view1触摸事件
        view1.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                
                //定义一个裁剪数据对象.随便定义一个就行,本demo用不到这个clipData.
                ClipData clipData = new ClipData(ClipData.newPlainText("view1", "aaa"));
                
                //定义一个拖拽阴影
                View.DragShadowBuilder myShadow = new View.DragShadowBuilder(view);
                
                //开始拖拽. 第三个参数在拖拽过程用来传递数据,这里我传view即被拖动的view自己,
                //后面可在DragEvent中获得这个参数view
                view.startDrag(clipData, myShadow, view, 0);
                
                return false;
            }
        });

        /**
         * 整理为一个通用的拖拽回调逻辑.所有容器view设置这个回调对象.
         *
         * 拖拽回调解释: 当一个view被拖拽的时候,系统会回调任何可见的view(包括被拖拽view自己)的OnDragListener,
         * 当然如果view没设置OnDragListener不会被系统回调.
         *
         */
        View.OnDragListener onDragListener1 = new View.OnDragListener() {
            @Override
            public boolean onDrag(View view, DragEvent dragEvent) {
                Log.i(TAG, "container.onDrag called======");
                switch (dragEvent.getAction()) {
                    case DragEvent.ACTION_DRAG_STARTED://开始.当有view被拖的时候收到此事件
//                        Log.i(TAG, "开始");
                        break;
                    case DragEvent.ACTION_DRAG_ENTERED://进入.当被拖view手指按压的位置进入本view的瞬间收到此事件
//                        Log.i(TAG, "进入");
                        break;
                    case DragEvent.ACTION_DRAG_LOCATION://位于.当被拖view手指按压的位置在本view上方的时候收到此事件
//                        Log.i(TAG, "位于");

                        //此时dragEvent里包含要被拖view
                        View draggingView = (View) dragEvent.getLocalState();
                        //当前容器
                        ViewGroup thisContainer = ((ViewGroup) view);
                        //被拖拽view覆盖的view
                        View coveredView = thisContainer.getChildAt(0);
                        //当拖拽的view跟被覆盖的view不同时
                        if (draggingView != coveredView) {
                            ViewGroup draggingViewContainer = (ViewGroup) draggingView.getParent();
                            //两个容器交换子view
                            thisContainer.removeView(coveredView);
                            draggingViewContainer.removeView(draggingView);
                            thisContainer.addView(draggingView);
                            draggingViewContainer.addView(coveredView);
                        }
                        break;
                    case DragEvent.ACTION_DROP://丢入.当被拖view在本view上方手指释放开,收到此事件
//                        Log.i(TAG, "丢入");
                        Log.i(TAG, "丢入view_container2");
                        break;
                    case DragEvent.ACTION_DRAG_EXITED://出去.当被拖view手指按压位置从本view拖出去收到此事件
//                        Log.i(TAG, "出去");
                        break;
                    case DragEvent.ACTION_DRAG_ENDED://结束.手指释放拖拽结束收到此事件.
//                        Log.i(TAG, "结束");
                        break;
                    default:
                        break;
                }
                //一定要为true
                return true;
            }
        };

        //container设置拖拽监听, 感知其他view的拖动
        view1_container.setOnDragListener(onDragListener1);
        view2_container.setOnDragListener(onDragListener1);
        view3_container.setOnDragListener(onDragListener1);
        
    }
}

这就是全部, so easy.

如有表达不好的地方还需大神指点.

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值