zoukankan      html  css  js  c++  java
  • Android 拖动任意View代码

    记得之前项目里面,写过这种需求,不过跟项目耦合的紧,又重网上找了几篇文章看了下,顺便也抄了下其他作者写的代码,如果需求场景比较简单,只是为了在当前手机屏幕里面拖动view,那么可以直接用本篇文章的代码,这里呢,有两个类,一个是自定义的ImageView,用于ImageView的任意拖拽效果,还有一个是fabButton的,可以任意拖拽fabButton。

    代码比较简单,下次有类似简单需求,就可以直接抄代码了,不然还得找半天。我们先看ImageView的.

    @SuppressLint("AppCompatCustomView")
    public class DragImageView extends ImageView {
    
        private int width;
        private int height;
        private int screenWidth;
        private int screenHeight;
        private Context context;
    
        //是否拖动
        private boolean isDrag = false;
        private float downX;
        private float downY;
    
    
        public DragImageView(Context context) {
            super(context);
            this.context = context;
        }
    
        public DragImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context = context;
        }
    
        public boolean isDrag() {
            return isDrag;
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            width = getMeasuredWidth();
            height = getMeasuredHeight();
            screenWidth = SystemUtils.getWindowWidth();
            screenHeight = SystemUtils.getWindowHeight() - SystemUtils.getStatusBarHeight();
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            super.onTouchEvent(event);
            if (this.isEnabled()) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        isDrag = false;
                        downX = event.getX();
                        downY = event.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        final float xDistance = event.getX() - downX;
                        final float yDistance = event.getY() - downY;
                        int l, r, t, b;
                        //当水平或者垂直滑动距离大于10,才算拖动事件
                        if (Math.abs(xDistance) > 10 || Math.abs(yDistance) > 10) {
                            isDrag = true;
                            l = (int) (getLeft() + xDistance);
                            r = l + width;
                            t = (int) (getTop() + yDistance);
                            b = t + height;
                            //不划出边界判断,此处应按照项目实际情况,因为本项目需求移动的位置是手机全屏,
                            // 所以才能这么写,如果是固定区域,要得到父控件的宽高位置后再做处理
                            if (l < 0) {
                                l = 0;
                                r = l + width;
                            } else if (r > screenWidth) {
                                r = screenWidth;
                                l = r - width;
                            }
                            if (t < 0) {
                                t = 0;
                                b = t + height;
                            } else if (b > screenHeight) {
                                b = screenHeight;
                                t = b - height;
                            }
    
                            this.layout(l, t, r, b);
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        setPressed(false);
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        setPressed(false);
                        break;
                }
                return true;
            }
            return false;
        }
    
    }

    接着在看看FabButton的吧,其实代码是差不多的

    public class DragFloatingActionButton extends FloatingActionButton {
    
        private int width;
        private int height;
        private int screenWidth;
        private int screenHeight;
        private Context context;
    
        //是否拖动
        private boolean isDrag = false;
        private float downX;
        private float downY;
    
    
        public DragFloatingActionButton(Context context) {
            super(context);
            this.context = context;
        }
    
        public DragFloatingActionButton(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context = context;
        }
    
        public boolean isDrag() {
            return isDrag;
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            width = getMeasuredWidth();
            height = getMeasuredHeight();
            screenWidth = SystemUtils.getWindowWidth();
            screenHeight = SystemUtils.getWindowHeight() - SystemUtils.getStatusBarHeight();
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            super.onTouchEvent(event);
            if (this.isEnabled()) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        isDrag = false;
                        downX = event.getX();
                        downY = event.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        final float xDistance = event.getX() - downX;
                        final float yDistance = event.getY() - downY;
                        int l, r, t, b;
                        //当水平或者垂直滑动距离大于10,才算拖动事件
                        if (Math.abs(xDistance) > 10 || Math.abs(yDistance) > 10) {
                            isDrag = true;
                            l = (int) (getLeft() + xDistance);
                            r = l + width;
                            t = (int) (getTop() + yDistance);
                            b = t + height;
                            //不划出边界判断,此处应按照项目实际情况,因为本项目需求移动的位置是手机全屏,
                            // 所以才能这么写,如果是固定区域,要得到父控件的宽高位置后再做处理
                            if (l < 0) {
                                l = 0;
                                r = l + width;
                            } else if (r > screenWidth) {
                                r = screenWidth;
                                l = r - width;
                            }
                            if (t < 0) {
                                t = 0;
                                b = t + height;
                            } else if (b > screenHeight) {
                                b = screenHeight;
                                t = b - height;
                            }
    
                            this.layout(l, t, r, b);
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        setPressed(false);
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        setPressed(false);
                        break;
                }
                return true;
            }
            return false;
        }
    
    }

    核心逻辑是在onTouchEvent里面的判断。有需要研究的可以自己分析。

    如果view需要处理点击事件呢。

    那么代码上的用法需要注意下,参考如下的姿势:

    dragView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.e("TEST", "onClick() dragView 111");
                    if (dragView.isDrag()) {
                        return;
                    }
                    Log.e("TEST", "onClick() dragView 222");
                    Toast.makeText(MainActivity.this, "哈哈", Toast.LENGTH_SHORT).show();
                }
            });

    写这篇是为了记录,像这种不经常写的代码(需求场景简单的),放个地方托管,方便下次复制粘贴。

  • 相关阅读:
    多线程编程
    Phthon环境搭建
    网站开发语言方案的选择
    NSTimer的一个误区
    一个tableview的自带动画
    一个扇形的动画效果
    一点两个uiview动画切换的体会
    关于gcd一些自己的理解。
    使用到定时器,单例和协议的一个小应用(2 )
    使用到定时器,单例和协议的一个小应用(1)
  • 原文地址:https://www.cnblogs.com/xing-star/p/13420054.html
Copyright © 2011-2022 走看看