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();
            }
        });

 

寫這篇是為了記錄,像這種不經常寫的代碼(需求場景簡單的),放個地方托管,方便下次復制粘貼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM