对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;
}
}