Activity或者view类中都有ontouchEvent回调方法,来接收touch事件,一个完整的手势是从ACTION_DOWN,到ACTION_UP结束。
在简单的情况下,我们只需要在onTouchEvent中写switch case语句,来处理三个动作(down、movw、up)。
ViewGroup作为一个parent是可以截获传向它的child的touch事件的。
那个事件是如何传递的呢?
处理过程是按照Touch事件从上向下传递,再按照是否消费的返回值从下到上返回,即如果view的onTouchEvent返回false,那么它将会不消费事件,这个事件交给它的上一级去消费,如果上一级也不消费,就再找上一级,这个过程最终会找到activity,如果activity也不消费,这个事件就消失了。
即隧道式向下分发,然后冒泡式向上处理。
dispatchTouchEvent:用来事件分发,其中这个方法调用了onIterceptTouchEvent和onTouchEven方法,一般来说,这个方法不重写。
onInterceptTouchEvent:用来事件拦截,ViewGroup类中源代码的事件,它retrun false,表示不拦截,我们可以自己去写返回值控制事件的分发。
onTouchEvent:用来事件处理,返回true代表这个view能处理该事件,事件将会终止向上传递,如果返回false,表示不能处理该事件,则把这个事件传递给这个控件的父view的onTouchEvent方法。
举例:
MainActivity里边套着MyViewGroup,MyViewGroup里边套着MyViewGroup1,MyViewGroup1里边套着MyView。
在这个例子中,点击123456这个TextView,查看Log日志:
1.activity_main.xml
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ws.day1024_02.MainActivity">
<com.ws.day1024_02.MyViewGroup
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ws.day1024_02.MyViewGroup1
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ws.day1024_02.MyView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="123456"
android:textSize="50sp"
android:clickable="true"
/>
</com.ws.day1024_02.MyViewGroup1>
</com.ws.day1024_02.MyViewGroup>
</RelativeLayout>
2. MainActivity.java
在Activity中没有事件拦截方法
importandroid.support.v7.app.AppCompatActivity;
importandroid.os.Bundle;
importandroid.util.Log;
importandroid.view.MotionEvent;
public classMainActivityextendsAppCompatActivity {
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//事件分发
@Override
public booleandispatchTouchEvent(MotionEvent ev) {
Log.d("flag","---->==========MainActivity----> dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
//事件响应
@Override
public booleanonTouchEvent(MotionEvent event) {
Log.d("flag","---->==========MainActivity---->onTouchEvent");
return super.onTouchEvent(event);
}
}
3. MyViewGroup.java
importandroid.content.Context;
importandroid.util.AttributeSet;
importandroid.util.Log;
importandroid.view.MotionEvent;
importandroid.widget.LinearLayout;
public classMyViewGroupextendsLinearLayout{
publicMyViewGroup(Context context) {
super(context);
}
publicMyViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
publicMyViewGroup(Context context, AttributeSet attrs,intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
//事件分发
@Override
public booleandispatchTouchEvent(MotionEvent ev) {
Log.d("flag","---->MyViewGroup----> dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
//事件拦截
@Override
public booleanonInterceptTouchEvent(MotionEvent ev) {
Log.d("flag","---->=========MyViewGroup----> onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
//事件响应
@Override
public booleanonTouchEvent(MotionEvent event) {
Log.d("flag","---->========MyViewGroup---->onTouchEvent");
return super.onTouchEvent(event);
}
}
4. MyViewGroup1.java
importandroid.content.Context;
importandroid.util.AttributeSet;
importandroid.util.Log;
importandroid.view.MotionEvent;
importandroid.widget.LinearLayout;
public classMyViewGroup1extendsLinearLayout {
publicMyViewGroup1(Context context) {
super(context);
}
publicMyViewGroup1(Context context, AttributeSet attrs) {
super(context, attrs);
}
publicMyViewGroup1(Context context, AttributeSet attrs,intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
//事件分发
@Override
public booleandispatchTouchEvent(MotionEvent ev) {
Log.d("flag","---->======MyViewGroup1----> dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
//事件拦截
@Override
public booleanonInterceptTouchEvent(MotionEvent ev) {
Log.d("flag","---->======MyViewGroup1----> onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
//事件响应
@Override
public booleanonTouchEvent(MotionEvent event) {
Log.d("flag","---->======MyViewGroup1---->onTouchEvent");
return super.onTouchEvent(event);
}
}
5. MyView.java
在View方法中,有事件拦截方法,但是不调用
importandroid.content.Context;
importandroid.util.AttributeSet;
importandroid.util.Log;
importandroid.view.MotionEvent;
importandroid.widget.TextView;
public classMyViewextendsTextView {
publicMyView(Context context) {
super(context);
}
publicMyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
publicMyView(Context context, AttributeSet attrs,intdefStyleAttr) {
super(context, attrs, defStyleAttr);
}
//事件分发
@Override
public booleandispatchTouchEvent(MotionEvent ev) {
Log.d("flag","---->====MyView----> dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
//事件响应
@Override
public booleanonTouchEvent(MotionEvent event) {
Log.d("flag","---->====MyView----->onTouchEvent");
return super.onTouchEvent(event);
}
}