View的坐标定位
1.安卓系统的坐标系是这样的,以左上角为原点,向右为x正,向下为Y正
2.view的坐标系是相对于父控件而言的。
所以首先明确:屏幕界面中存在两个坐标系,1.屏幕坐标系。2.view自身坐标系(以其父View为坐标参考系)于是引申出以下概念:
屏幕坐标系 getTop(); //获取子View左上角距父View顶部的距离
getLeft(); //获取子View左上角距父View左侧的距离
getBottom(); //获取子View右下角距父View顶部的距离
getRight(); //获取子View右下角距父View左侧的距离
getRawX() //触摸时,触摸点相对于屏幕坐标系顶边和左边的距离
getRawY() //触摸时,触摸点相对于屏幕坐标系顶边和左边的距离
view自身坐标系 getX() //触摸时,触摸点相对于View自身坐标系顶边和左边的距离
getY() //触摸时,触摸点相对于View自身坐标系顶边和左边的距离
看图理解:
代码实例,实现一个可以自由拖动的view:
我们写了一个自定义view,想要拖动它,实现这个有3种方式,先看第一种因为发生了触摸事件,拖动的过程触发了:按下,移动。因为拖动不包含抬起,所以暂时不考虑抬起的事件。
于是,很自然想到要在OnTouchEvent里处理,代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
laseY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x-lastX;
int offsetY = y-laseY;
layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
//第二种方式:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
laseY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x-lastX;
int offsetY = y-laseY;
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
//第三种方式:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();//触摸点相对屏幕左上角的坐标距离
int y = (int) event.getY();//触摸点相对屏幕左上角的坐标距离
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
laseY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x-lastX;
int offsetY = y-laseY;
layoutView(offsetX,offsetY);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
private void layoutView( int offsetX, int offsetY) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
params.leftMargin = getLeft()+offsetX;
params.topMargin = getTop()+offsetY;
setLayoutParams(params);
}
完整代码如下:
/**
* Created by HY on 2017/5/31.
*/
public class TView extends View {
Paint paint;
private Bitmap bitmap;
private int lastX;
private int laseY;
private Scroller scroller;
public TView(Context context) {
this(context,null);
}
public TView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public TView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
paint = new Paint();
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
scroller = new Scroller(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
laseY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x-lastX;
int offsetY = y-laseY;
// layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);
// offsetLeftAndRight(offsetX);
// offsetTopAndBottom(offsetY);
layoutView(offsetX,offsetY);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
private void layoutView( int offsetX, int offsetY) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
params.leftMargin = getLeft()+offsetX;
params.topMargin = getTop()+offsetY;
setLayoutParams(params);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap,0,0,paint);
}
}