View拖拽 自定义绑定view拖拽的工具类

由于工作需求,需要用到这种处理方法所以我就写了这个

废话不多说先看效果图

接下来就看代码吧 DragDropManager

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 拖拽工具类
 */
public class DragDropManager implements View.OnTouchListener {

    /**
     * View 集合
     */
    private List<View> viewList;

    private static Activity mActivity;
    private static DragDropManager mManager;

    private Map<View, ViewInfo> mViewMap;

    /**
     * 窗口管理器,用于显示条目的快照
     */
    private WindowManager mWindowManager;

    /**
     * 窗口管理的布局参数
     */
    private WindowManager.LayoutParams mWindowLayoutParams;

    /**
     * 悬浮的imageView
     */
    private ImageView mDragPhotoView;
    private Bitmap mDragPhotoBitmap;
    private float moveX;
    private float moveY;

    private IDragDropListener listener;

    public DragDropManager() {
        viewList = new ArrayList<>();
        mViewMap = new HashMap<>();
    }

    public static DragDropManager getInstance(Activity activity) {
        mActivity = activity;
        if (mManager == null) {
            mManager = new DragDropManager();
        }
        return mManager;
    }

    /**
     * 绑定view
     */
    public void bindView(View... views) {
        viewList.clear();
        for (View view : views) {
            view.setOnTouchListener(this);
            if(view instanceof TextView){
                view.setOnClickListener(null);
            }
            viewList.add(view);
        }
    }

    /**
     * 添加view
     *
     * @param views
     */
    public void addView(View... views) {
        for (View view : views) {
            view.setOnTouchListener(this);
            viewList.add(view);
        }
    }

    /**
     * 设置监听事件
     * @param listener
     */
    public void setListener(IDragDropListener listener){
        this.listener = listener;
    }

    @Override
    public boolean onTouch(View view, MotionEvent event) {

        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                Log.i("tag", "生成图像");
                //首先初始化每个控件的坐标信息
                initViewLayout();
                //判断出点击的是哪个控件 并悬浮出哪个控件
                createDragPhotoView(view);
                moveX = event.getX();
                moveY = event.getY();
                //回调监听
                if(listener != null){
                    listener.startDragDrop(view.getId());
                }
                break;
            case MotionEvent.ACTION_MOVE:
                mWindowLayoutParams.x = (int) (mViewMap.get(view).x + (event.getX() - moveX));
                mWindowLayoutParams.y = (int) (mViewMap.get(view).y + (event.getY() - moveY));
                mWindowManager.updateViewLayout(mDragPhotoView, mWindowLayoutParams);
                Log.i("tag", "移动图像 x:"+(view.getX() + (event.getX() - moveX))+"  y:" + (view.getY() + (event.getY() - moveY)));
                break;
            case MotionEvent.ACTION_UP:
                Log.i("tag", "去掉图像");

                //
                if(listener != null) {
                    for (View tempView : viewList) {
                        if (tempView.getId() != view.getId()) {
                            ViewInfo viewInfo = mViewMap.get(tempView);
                            if (event.getRawX() > viewInfo.x && event.getRawY() > viewInfo.y
                                    && event.getRawX() < (viewInfo.x + viewInfo.width) && event.getRawY() < (viewInfo.y + viewInfo.height)) {
                                listener.endDragDrop(view.getId(),tempView.getId());
                                break;
                            }
                        }
                    }
                }

                // 移除快照
                if (mDragPhotoView != null) {
                    mWindowManager.removeView(mDragPhotoView);
                    mDragPhotoView.setImageDrawable(null);
                    mDragPhotoBitmap.recycle();
                    mDragPhotoBitmap = null;
                    mDragPhotoView = null;
                }
                break;
        }
        return false;
    }

    /**
     * 初始化每个控件的坐标信息
     */
    private void initViewLayout() {
        mViewMap.clear();
        int[] location = new int[2];
        for (View view : viewList) {
            view.getLocationInWindow(location);
            ViewInfo viewInfo = new ViewInfo(view, location[0], location[1], view.getMeasuredHeight(), view.getMeasuredWidth());
            mViewMap.put(view, viewInfo);
        }
    }

    /**
     * 创建拖拽快照
     */
    private void createDragPhotoView(View view) {
        // 进行绘图缓存
        view.setDrawingCacheEnabled(true);
        // 提取缓存中的图片
        mDragPhotoBitmap = Bitmap.createBitmap(view.getDrawingCache());
        // 获取当前窗口管理器
        mWindowManager = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
        // 创建布局参数
        mWindowLayoutParams = new WindowManager.LayoutParams();
        mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.gravity = Gravity.TOP | Gravity.START;
        mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; // 期望的图片为半透明效果,但设置其他值并没有看到不一样的效果
        // 下面这些参数能够帮助准确定位到选中项点击位置
        mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
        mWindowLayoutParams.windowAnimations = 0; // 无动画
        mWindowLayoutParams.alpha = 0.6f; // 微透明

        mWindowLayoutParams.x = (int) mViewMap.get(view).x;
        mWindowLayoutParams.y = (int) mViewMap.get(view).y;
        mDragPhotoView = new ImageView(mActivity);
        mDragPhotoView.setImageBitmap(mDragPhotoBitmap);
        mWindowManager.addView(mDragPhotoView, mWindowLayoutParams);
    }

    /**
     * 监听接口
     */
    public interface IDragDropListener{

        /**
         * 开始拖动
         * @param startViewId 返回当前view的ID
         */
        void startDragDrop(int startViewId);

        /**
         * 结束拖动
         * @param startViewId 返回当前view的ID
         * @param endViewId 返回覆盖在某个view的ID
         */
        void endDragDrop(int startViewId,int endViewId);
    }

    /**
     * 记录当前view的坐标和宽高信息
     */
    class ViewInfo {

        private View view;
        private float x;
        private float y;
        private float height;
        private float width;

        public ViewInfo(View view, float x, float y, float height, float width) {
            this.view = view;
            this.x = x;
            this.y = y;
            this.height = height;
            this.width = width;
        }
    }
}

使用方法

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

        TextView textView = findViewById(R.id.tvTitle);
        TextView tegg = findViewById(R.id.tvTitlegg);
        Button btnTuo = findViewById(R.id.btnTuo);
        dragDropManager = DragDropManager.getInstance(this);
        dragDropManager.bindView(textView,btnTuo,tegg);
        dragDropManager.setListener(new DragDropManager.IDragDropListener() {
            @Override
            public void startDragDrop(int startViewId) {
                Toast.makeText(MainActivity.this,"开始悬浮",0).show();
            }

            @Override
            public void endDragDrop(int startViewId, int endViewId) {
                Toast.makeText(MainActivity.this,"开始悬浮 sID:" + startViewId + "//endID : " + endViewId,0).show();
            }
        });

        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"text dianji",0).show();
            }
        });
        btnTuo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"btnTuo dianji",0).show();
            }
        });
    }
}

代码demo
demo下载

原文地址:https://www.cnblogs.com/woaixingxing/p/8986790.html

时间: 2024-08-29 23:58:03

View拖拽 自定义绑定view拖拽的工具类的相关文章

使用knockout-sortable实现对自定义菜单的拖拽排序

在开始之前,照例,我们先看效果和功能实现. 关于自定义菜单的实现,这里就不多说了,需要了解的请访问:http://www.cnblogs.com/codelove/p/4838766.html 这里需要说明的是排序的实现. 我们先来看看关键的页面代码: <div class="row"> <div class="col-lg-12 full-width" id="leftMenus"> <div class=&quo

拖拽+自定义滚动条

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>拖拽+滚动条</title> <meta name="description" content

自定义滚动条和拖拽

实现自定义滚动条和拖拽滚动效果 <div class="dropDownMenu"> <ul> <li><a href="#">平缝机</a></li> <li><a href="#">包缝机</a></li> <li><a href="#">绷缝机</a></li&

Xcode如何拖拽选中文字、拖拽代码

不管是文本编辑,还是代码工具,一般都提供了用鼠标拖拽选中文字到指定地方的功能,但是在Xcode里貌似这样有点儿难,你会发现当想拖动的时候会有时候成功,但是大部分时间都是又处于选择状态.一开始我以为是Mac系统的原因,后来发现在其他地方:浏览器就可以拖动,我想这可能是Xcode里去掉了,但是有时候能拖拽是怎么回事.好吧,我不coding了,非得找出来. 废话不多说了: 点击选中的代码(文字),不要移动和松开鼠标左键,当竖线变成箭头之后就可以拖动了,其实不需要多少时间,基本上就是:不要直接点鼠标左键

IOS 自定义UIBUTTON 直接拖个xib 就能在button上显示多行文本 并且添加了点击的效果

拖个button继承一下  几行代码 就搞定 自用效果还行 IOS 自定义UIBUTTON 直接拖个xib 就能在button上显示多行文本 并且添加了点击的效果,布布扣,bubuko.com

128、View 绘制流程 &amp; 自定义View

记清楚函数调用的顺序才能准确地进行调用. 根据调用链,可将整个绘制过程分为三部分:Measure - Layout - Draw Measure 过程 1. 测量过程由上至下,在measure过程的最后,每个视图将存储自己的尺寸大小和测量规格. 2. measure过程会为一个View及其所有子节点的mMeasureWidth和mMeasuredHeight变量赋值, 该值可以通过getMeasuredWidth和getMeasuredHeight方法获得. 3. measure过程的核心方法:

Android XML中引用自定义内部类view的四个why

今天碰到了在XML中应用以内部类形式定义的自定义view,结果遇到了一些坑.虽然通过看了一些前辈写的文章解决了这个问题,但是我看到的几篇都没有完整说清楚why,于是决定做这个总结. 使用自定义内部类view的规则 本文主要是总结why,所以先把XML布局文件中引用内部类的自定义view的做法摆出来,有四点: 自定义的类必须是静态类: 使用view作为XML文件中的tag,注意,v是小写字母,小写字母v,小写字母v: 添加class属性,注意,没有带android:命名空间的,表明该自定义view

Android中如何优雅地自定义一个View

Android中自定义View的实现比较简单,无非就是继承父类,然后重载方法,即便如此,在实际编码中难免会遇到一些坑,我把自己遇到的一些问题和解决方法总结一下,希望对广大码友们有所帮助. 注意点① 用xml定义Layout时,Root element 最好使用merge 当我们需要继承一个布局比较复杂的ViewGroup(比较多的是LinearLayout.RelativeLayout)时,通常会用xml来写布局,然后在自定义的View类中inflate这个定义了layout的xml文件. 首先

[翻译]在objective c创建自定义collection view样式

创建自定义collection样式 苹果在ios6中新增了一个更加易于创建和管理复杂用户界面的类:collection view.在此之前ios6上面用于展示多项列表的是table view,虽然名称是表格但它展示信息的形式并不是表格形式,而是垂直列表,当然在实际设计展示垂直可滚动的文本型列表时非常有用,但是你会遇到许多垂直可滚动的列表所存在的局限性,比如不能水平滚动,每行只有一项单元格,没有复杂的样式,在ios6之前你想要做到这些事情,只能靠自定义扩展. 在ios6 平台介绍了一个新的类:co