Android 自定义View之MotionEvent方法详解
1.事件类型
这里就引入关于 MotionEvent 的一个重要概念,事件类型。事件类型就是指对象所代表的动作。比如说,当你的一个手指在屏幕上滑动一下时,系统会产生一系列的触摸事件对象,他们所代表的动作有所不同。有的事件代表你手指按下这个动作,有的事件代表你手指在屏幕上滑动,还有的事件代表你手指离开屏幕。常用的如下几种:
ACTION_DOWN:手指按下
ACTION_MOVE:手指一动
ACTION_UP:手指抬起
ACTION_CANCEL:事件取消(极少用到)
2.事件序列
正常情况下,手指触摸屏幕的行为,会触发一系列点击事件,常见的如下几种:
点击屏幕后离开松开,事件序列为 DOWN → UP
点击屏幕滑动一会再松开,事件序列为 DOWN → MOVE → ... → MOVE → UP
3.MotionEvent getX() getY() Demo
3.1.布局
<?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>
3.2.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;
}
});
}
}
3.3.图解
3.4.效果
通过MotionEvent对象我们可以得到点击事件发生的x和y坐标。
系统为我们提供了getX() / getY()和getRawX() / getRawY()。
getX() getY()返回的是相对于相对当前View的左上角的x和y坐标。
getRawX() getRawY()返回的是相对于手机屏幕左上角的x和y坐标。
4.MotionEvent getRawX() getRawY() Demo
4.1.布局
<?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>
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;
}
});
}
}
4.3.效果
5.滑动的最小距离TouchSlop
TouchSlop是系统所能识别出的被认为是滑动的最小距离。这是一个常量,就是说,当你手指在屏幕滑动大于这个常量,系统才会认定你滑动屏幕了,它和设备有关,不同的设备这个值可能是不同的。
我们可以通过如下代码获取这个常量:ViewConfiguration.get(this).getScaledTouchSlop();
代码:
float TouchSlop= ViewConfiguration.get(MotionEventActivity.this).getScaledTouchSlop();
Log.d("TAG", "TouchSlop----:"+TouchSlop);
效果:
即当前设备下滑动的最小距离是24
6.总结
关于OnTouchEvent(MotionEvent事件)事件的层级传递。我们都知道如果给一个控件注册了touch事件,每次点击它的时候都会触发一系列的ACTION_DOWN,ACTION_MOVE,ACTION_UP等事件。这里需要注意,如果你在执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再得到执行了。简单的说,就是当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action。
推荐阅读
-
Android自定义View之RadioGroup实现跨多行显示
-
Android数据持久化之读写SD卡中内容的方法详解
-
Android之采用execSQL与rawQuery方法完成数据的添删改查操作详解
-
Android自定义引导玩转ViewPager的方法详解
-
Android自定义抛出异常的方法详解
-
Android开发之PopupWindow创建弹窗、对话框的方法详解
-
Android开发之自定义view实现通讯录列表A~Z字母提示效果【附demo源码下载】
-
Android开发之HttpClient异步请求数据的方法详解【附demo源码下载】
-
Android自定义View绘制的方法及过程(二)
-
android自定义view之模拟qq消息拖拽删除效果