自定义View MotionEvent方法详解

一.事件类型

这里就引入关于 MotionEvent 的一个重要概念,事件类型。事件类型就是指对象所代表的动作。比如说,当你的一个手指在屏幕上滑动一下时,系统会产生一系列的触摸事件对象,他们所代表的动作有所不同。有的事件代表你手指按下这个动作,有的事件代表你手指在屏幕上滑动,还有的事件代表你手指离开屏幕。常用的如下几种:

 

ACTION_DOWN:手指按下

ACTION_MOVE:手指一动

ACTION_UP:手指抬起

ACTION_CANCEL:事件取消(极少用到)

 

 

 

 

 

二.事件序列

正常情况下,手指触摸屏幕的行为,会触发一系列点击事件,常见的如下几种:

点击屏幕后离开松开,事件序列为 DOWN → UP

点击屏幕滑动一会再松开,事件序列为 DOWN → MOVE → ... → MOVE → UP

 

 

 

 

三.MotionEvent getX() getY() Demo

 

布局

<strong><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:id="@+id/activity_motionevent_textview"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:clickable="true"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:background="#FF0000"
    android:textColor="#FFFFFF"
    android:text="Android 自定义View之MotionEvent方法详解"/>

</RelativeLayout></strong>

 

Java代码

public class MotionEventActivity extends AppCompatActivity {

    private TextView textView;
    private int lastX;
    private int lastY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_motionevent);
        textView= (TextView) findViewById(R.id.activity_motionevent_textview);
        textView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                int action=motionEvent.getAction();
                int x= (int) motionEvent.getX();
                int y= (int) motionEvent.getY();
                switch(action){
                    case MotionEvent.ACTION_DOWN://按下
                        lastX=x;
                        lastY=y;
                        Log.d("TAG", "按下坐标----:("+lastX+","+lastY+")");
                        break;
                    case MotionEvent.ACTION_MOVE://移动
                        float offsetX=x-lastX;
                        float offsetY=y-lastY;
                        Log.d("TAG", "移动X轴位移量offsetX----:"+offsetX);
                        Log.d("TAG", "移动X轴位移量offsetY----:"+offsetY);
                        break;
                    case MotionEvent.ACTION_UP://抬起
                        Log.d("TAG", "抬起坐标----:("+x+","+y+")");
                        break;
                }
                return false;
            }
        });
    }

}

 

图解

 

 

效果

 

通过MotionEvent对象我们可以得到点击事件发生的x和y坐标。

系统为我们提供了getX() / getY()和getRawX() / getRawY()。

 

getX() getY()返回的是相对于相对当前View的左上角的x和y坐标

 

getRawX() getRawY()返回的是相对于手机屏幕左上角的x和y坐标

 

 

 

 

 

四.MotionEvent getRawX() getRawY() Demo

 

布局

<strong><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:id="@+id/activity_motionevent_textview"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:clickable="true"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:background="#FF0000"
    android:textColor="#FFFFFF"
    android:text="Android 自定义View之MotionEvent方法详解"/>

</RelativeLayout></strong>

 

 

Java代码

public class MotionEventActivity extends AppCompatActivity {

    private TextView textView;
    private int lastX;
    private int lastY;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_motionevent);
        textView= (TextView) findViewById(R.id.activity_motionevent_textview);
        textView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                int action=motionEvent.getAction();
                int x= (int) motionEvent.getRawX();
                int y= (int) motionEvent.getRawY();
                switch(action){
                    case MotionEvent.ACTION_DOWN://按下
                        lastX=x;
                        lastY=y;
                        Log.d("TAG", "按下坐标----:("+lastX+","+lastY+")");
                        break;
                    case MotionEvent.ACTION_MOVE://移动
                        float offsetX=x-lastX;
                        float offsetY=y-lastY;
                        Log.d("TAG", "移动X轴位移量offsetX----:"+offsetX);
                        Log.d("TAG", "移动X轴位移量offsetY----:"+offsetY);
                        break;
                    case MotionEvent.ACTION_UP://抬起
                        Log.d("TAG", "抬起坐标----:("+x+","+y+")");
                        break;
                }
                return false;
            }
        });
    }

}

 

效果

 

 

 

 

 

五.滑动的最小距离TouchSlop

TouchSlop是系统所能识别出的被认为是滑动的最小距离。这是一个常量,就是说,当你手指在屏幕滑动大于这个常量,系统才会认定你滑动屏幕了,它和设备有关,不同的设备这个值可能是不同的。

我们可以通过如下代码获取这个常量:ViewConfiguration.get(this).getScaledTouchSlop();

 

代码

float TouchSlop= ViewConfiguration.get(MotionEventActivity.this).getScaledTouchSlop();
Log.d("TAG", "TouchSlop----:"+TouchSlop);

 

效果

即当前设备下滑动的最小距离是24

 

 

 

 

 

 

六.总结

关于OnTouchEvent(MotionEvent事件)事件的层级传递。我们都知道如果给一个控件注册了touch事件,每次点击它的时候都会触发一系列的ACTION_DOWN,ACTION_MOVE,ACTION_UP等事件。这里需要注意,如果你在执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再得到执行了。简单的说,就是当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值