Android自定义View实现跟随手指移动

2022-08-17 16:12:18

对View的移动,实现的方法有好几种,原理是通过改变View的位置来移动View,下面来实现这样的效果动画的方法通过改变View的tranlationX和tranlationY的值来实现移动,首先来写...

对View的移动,实现的方法有好几种,原理是通过改变View的位置来移动View,下面来实现这样的效果

Android自定义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 boo编程lean 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:
       MZwjH 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;
//        setTransphplationX(tranX);
//        setTranslationY(tranY);
//        break;
//      case MotionEvent.ACTION_UP:
//
//        break;
//      default:
//        break;
//    }
    //-----------------------------------------------

    //layout方法实现
//    switch (event.getAction()) {
//      case MotionEvjavascriptent.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;
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。