首頁 > 軟體

Android自定義View實現跟隨手指移動

2022-08-17 18:00:32

對View的移動,實現的方法有好幾種,原理是通過改變View的位置來移動View,下面來實現這樣的效果

  • 動畫的方法

通過改變View的tranlationX和tranlationY的值來實現移動,首先來寫一個自定義View類,重寫onTouchEvent方法,實現構造方法

public class MyView extends View {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return true;//這裡我們要消費這個事件,所以返回了true
    }
}

關於移動的處理邏輯都在onTouchEvent方法中,下面的程式碼主要針對onTouchEvent方法修改,其它程式碼不再貼上了

首先要獲取手指點選移動在螢幕上的座標,使用

int x = (int)event.getRawX();//獲取x軸上的位置 
int y = (int)event.getRawY();//獲取y軸上的位置

處理事件的模板程式碼

switch(event.getAction()){
    case MotionEvent.ACTION_DOWN://點選事件
        break;
    case MotionEvent.ACTION_MOVE://移動事件
        break;
    case MotionEvent.ACTION_UP://離開事件
        break;
    default:
        break;
}

通過判斷事件的型別,將在ACTION_MOVE事件中計算移動前後的差值來設定View的translationX和translationY值來改變View的位置,這裡需要記錄上次的位置,所以需要2個變數,程式碼如下

private int mLaxtX;
private int mLaxtY;

  @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getRawX();
        int y = (int) event.getRawY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                int deltaX = x - mLastX;//計算x座標上的差值
                int deltaY = y - mLastY;//計算y座標上的差值
                float tranX = getTranslationX() + deltaX ;//要平移的x值
                float tranY = getTranslationY() + deltaY;//要平移的y值
                setTranslationX(tranX);//設定值
                setTranslationY(tranY);
                break;
            case MotionEvent.ACTION_UP:

                break;
            default:
                break;
        }
        mLastX = x;//記錄上次的座標
        mLastY = y;
        return true;
    }
  • layout方法

View在繪製的時候,會呼叫onLayout方法來設定顯示的位置,可以通過這個方法來實現移動

//layout方法實現
switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                //計算偏移量
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                //重新佈局
                layout(getLeft() + offsetX, getTop() + offsetY,
                        getRight() + offsetX, getBottom() + offsetY);
                //也可以使用下面這種方法
//                offsetLeftAndRight(offsetX);
//                offsetTopAndBottom(offsetY);
                break;
            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }
        mLastX = x;
        mLastY = y;
  • LayoutParams

LayoutParams儲存了一個View的佈局引數,通過改變這個引數,重繪View也可以實現移動

//LayoutParams方法
 switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                //範例程式碼的父View是LinearLayout
                LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
                layoutParams.leftMargin = getLeft() + offsetX;
                layoutParams.topMargin = getTop() + offsetY;
                //下面這兩句都可以使用,setLayoutParams也會呼叫requestLayout
                //                setLayoutParams(layoutParams);
                requestLayout();
                break;
            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }

這裡先介紹這幾種方法

完整程式碼如下:

public class MyView extends View {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private int mLastX;
    private int mLastY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getRawX();
        int y = (int) event.getRawY();
        //動畫實現移動程式碼
        //--------------------------------------------------
//        switch (event.getAction()) {
//            case MotionEvent.ACTION_DOWN:
//
//                break;
//            case MotionEvent.ACTION_MOVE:
//                int delaltax = x - mLastX;
//                int delaltaY = y - mLastY;
//                float tranX = getTranslationX() + delaltax;
//                float tranY = getTranslationY() + delaltaY;
//                setTranslationX(tranX);
//                setTranslationY(tranY);
//                break;
//            case MotionEvent.ACTION_UP:
//
//                break;
//            default:
//                break;
//        }
        //-----------------------------------------------

        //layout方法實現
//        switch (event.getAction()) {
//            case MotionEvent.ACTION_DOWN:
//                break;
//            case MotionEvent.ACTION_MOVE:
//                //計算偏移量
//                int offsetX = x - mLastX;
//                int offsetY = y - mLastY;
//                //重新佈局
//                layout(getLeft() + offsetX, getTop() + offsetY,
//                        getRight() + offsetX, getBottom() + offsetY);
//                //也可以使用下面這種方法
                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);
//                break;
//            case MotionEvent.ACTION_UP:
//                break;
//            default:
//                break;
//        }
        //---------------------------------------------

        //LayoutParams方法
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                //範例程式碼的父View是LinearLayout
                LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
                layoutParams.leftMargin = getLeft() + offsetX;
                layoutParams.topMargin = getTop() + offsetY;
                //下面這兩句都可以使用,setLayoutParams也會呼叫requestLayout
                //                setLayoutParams(layoutParams);
                requestLayout();
                break;
            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }

        mLastX = x;
        mLastY = y;
        return true;
    }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com