自定义View(三):View的触摸与滑动

1、Android的坐标轴

android的坐标轴是以屏幕的左上角为原点,水平向右为x轴正方向,垂直向下为y轴正方向。View有一套方法来获取自身的位置。

getLeft():获取View最左边在父布局中的位置

getRight():获取View最右边在父布局中的位置

getTop():获取View最上边在父布局中的位置

getBottom():获取View最下边在父布局中的位置

2、View的触摸与滑动要用到那些方法

当View被触摸会时调用onTouchEvent(MotionEvent event)方法,滑动时则需要利用layout()方法来重新定位View的位置,以达到滑动的效果。
首先我们来研究一下onTouchEvent(MotionEvent event)方法,我们知道触摸常常有三种方式:触摸屏幕、在屏幕上拖动、触摸点离开屏幕,我们可以通过MotionEvent的getAntion来判断。

MotionEvent.ACTION_DOWN:触摸屏幕

MotionEvent.ACTION_MOVE:在屏幕上拖动

MotionEvent.ACTION_UP:触摸点离开屏幕

3、重写onTouchEvent方法

新建MyView类继承View类并实现他的四个构造方法,重写onTouchEvent方法,代码如下:

@Override
public boolean onTouchEvent(MotionEvent event) {
    int x= (int) event.getX();//获取触摸位置
    int y= (int) event.getY();
    
    switch (event.getAction()){
        //触摸屏幕
        case MotionEvent.ACTION_DOWN:
            beginX=x;
            beginY=y;
            Log.w("debug","down_x:"+x+"   down_y:"+y);
            break;
        
        //在屏幕上拖动
        case MotionEvent.ACTION_MOVE:
            //计算拖动距离
            int moveX=x-beginX;
            int moveY=y-beginY;
            Log.w("debug","move_x"+moveX+"   move_y:"+moveY);
            break;
        
        //触摸离开屏幕
        case MotionEvent.ACTION_UP:
            Log.w("debug","up_x"+x+"   up_y:"+y);
            break;
    }
    return true;
}


beginX和begin分别记录触摸屏幕时的位置,值得注意的是event.getX()和event.getY()都是根据View的左上角为原点,点击控件时在屏幕上拖动一小段距离可以看到如下运行结果:

自定义View(三):View的触摸与滑动

4、通过layout()方法实现滑动

首先讲一下layout方法的参数

layout(int l, int t, int r, int b)

很显然要传的是View的新位置的四个坐标点。

l:View在父布局中最左边的坐标点

t:View在父布局中最上边的坐标点

r:View在父布局中最右边的坐标点

b:View在父布局中最下边的坐标点

自定义View(三):View的触摸与滑动

滑动之后View的新位置为旧坐标+滑动的距离,View的滑动就实现了,上完整代码:

public class MyView extends View {
    private int beginX,beginY;


    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x= (int) event.getX();//获取触摸位置
        int y= (int) event.getY();
        switch (event.getAction()){
            //触摸屏幕
            case MotionEvent.ACTION_DOWN:
                beginX=x;
                beginY=y;
                Log.w("debug","down_x:"+x+"   down_y:"+y);
                break;
            //在屏幕上拖动
            case MotionEvent.ACTION_MOVE:
                //计算拖动距离
                int moveX=x-beginX;
                int moveY=y-beginY;
                layout(getLeft()+moveX,getTop()+moveY,getRight()+moveX,getBottom()+moveY);
                Log.w("debug","move_x"+moveX+"   move_y:"+moveY);
                break;
            //触摸离开屏幕
            case MotionEvent.ACTION_UP:
                Log.w("debug","up_x"+x+"   up_y:"+y);
                break;
        }
        return true;
    }
}

5、源码链接

https://github.com/Hasagit/LayoutDemo.git