自定义view(一)View坐标系与触摸事件

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


}

最后效果:

你可能感兴趣的:(android,控件)