自定义控件中,使自定义控件根据手势滑动而移动的实现方式有很多,这篇文章讲解通过layout()方法,实现移动。
我们知道,android 系统在控件绘制的过程中,会通过onLayout()方法来设置显示的位置,那么,我们是否可以调用相关方法,通过改变view的布局位置,实现view随手势移动呢,答案是肯定的,通过layout()方法,即可实现。调用layout()方法,会使View对自己重新布局。
下面来看代码实现:
在我们的自定义view中,重写onTouchEvent 方法,其获取坐标,可以用event.getRawX()或者event.getX(),先看具体实现,在讲解不同之处:
1.使用getRowX()实现
@Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = (int) event.getRawX();
mLastY = (int) event.getRawY();
Log.e("DragView","ACTION_DOWN:" + "rowX:" + mLastX +";getX:"+event.getX());
break;
case MotionEvent.ACTION_MOVE:
int moveX = (int) event.getRawX();
int moveY = (int) event.getRawY();
int offsetX = moveX - mLastX;
int offsetY = moveY -mLastY;
layout(getLeft() + offsetX,getTop() + offsetY,
getRight() + offsetX ,getBottom() + offsetY);
mLastX = moveX;
mLastY = moveY;
Log.e("DragView","ACTION_MOVE:" + "rowX:" + event.getRawX() +";getX:"+event.getX());
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
2.使用getX()实现
@Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = (int) event.getX();
mDownY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveX = (int) event.getX();
int moveY = (int) event.getY();
int offsetX = moveX - mDownX;
int offsetY = moveY - mDownY;
layout(getLeft() + offsetX,getTop() + offsetY,
getRight() + offsetX ,getBottom() + offsetY);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
大家看出有什么区别了吗?显而易见,当用getRowX()时,需要用一个变量,记录上一次的位置,而当getX()时,则不需要。这是为什么呢。原因就是所使用的坐标系不同。
在Android系统中,存在两种坐标系,一种是Android坐标系,一种是视图坐标系。
android 坐标系,是将屏幕最左上角的坐顶点作为Android坐标系的原点从这个点向右,是X轴的正方向,从该点向下是Y轴的正方向,系统提供了getLocationOnScreen()来获取android坐标系中点的位置,同时,在触摸事件中getRowX()和getRowY()方法所获得的坐标,同样也是Android坐标系中的坐标。Android坐标系如图所示:
![Android坐标系](https://img-blog.csdn.net/20161126152933582)
另一种坐标系是视图坐标系,它描述了子视图在父视图中的位置关系,在该坐标系下,原点是父视图的左上角位置,如图所示:
![视图坐标系](https://img-blog.csdn.net/20161126153620295)
通过对这两种试图的了解,相信对之前的代码应该没有什么疑问了。