重写的view:
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
public class EventButton extends Button {
public EventButton(Context context) {
super(context);
}
public EventButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public EventButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("Button onTouchEvent:" + event.getAction());
// switch (event.getAction()) {
// case MotionEvent.ACTION_DOWN:
// return false;
// default:
// break;
// }
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
System.out.println("Buttonon dispatchTouchEvent:" + event.getAction());
// switch (event.getAction()) {
// case MotionEvent.ACTION_MOVE:
// return false;
// default:
// break;
// }
return super.dispatchTouchEvent(event);
}
}
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
public class EventButton extends Button {
public EventButton(Context context) {
super(context);
}
public EventButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public EventButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("Button onTouchEvent:" + event.getAction());
// switch (event.getAction()) {
// case MotionEvent.ACTION_DOWN:
// return false;
// default:
// break;
// }
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
System.out.println("Buttonon dispatchTouchEvent:" + event.getAction());
// switch (event.getAction()) {
// case MotionEvent.ACTION_MOVE:
// return false;
// default:
// break;
// }
return super.dispatchTouchEvent(event);
}
}
重写的viewGroup:
package com.example.testviewevent;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.MeasureSpec;
public class EventViewGroup extends ViewGroup {
public EventViewGroup(Context context) {
super(context);
}
public EventViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public EventViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childLeft = 0;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
final int childWidth = child.getMeasuredWidth();
child.layout(childLeft, 0, childLeft + childWidth,
child.getMeasuredHeight());
childLeft += childWidth;
}
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
System.out.println("viewGroup dispatchTouchEvent:" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("viewGroup onTouchEvent:" + event.getAction());
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
System.out.println("viewGroup onInterceptTouchEvent:" + ev.getAction());
return true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// 测量页面及子控件宽度和高度
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"Workspace can only be used in EXACTLY mode.");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"Workspace can only be used in EXACTLY mode.");
}
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
}
}
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.MeasureSpec;
public class EventViewGroup extends ViewGroup {
public EventViewGroup(Context context) {
super(context);
}
public EventViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public EventViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childLeft = 0;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
final int childWidth = child.getMeasuredWidth();
child.layout(childLeft, 0, childLeft + childWidth,
child.getMeasuredHeight());
childLeft += childWidth;
}
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
System.out.println("viewGroup dispatchTouchEvent:" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("viewGroup onTouchEvent:" + event.getAction());
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
System.out.println("viewGroup onInterceptTouchEvent:" + ev.getAction());
return true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// 测量页面及子控件宽度和高度
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"Workspace can only be used in EXACTLY mode.");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"Workspace can only be used in EXACTLY mode.");
}
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
}
}
测试Activity:
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActionBar.LayoutParams;
import android.graphics.Color;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
public class MainActivity extends Activity {
private EventButton btn;
private EventViewGroup viewGroup;
@SuppressLint("NewApi") @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (EventButton) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("Button was Clicked!");
}
});
viewGroup = (EventViewGroup) findViewById(R.id.viewGroup);
viewGroup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("ViewGroup was Clicked!");
}
});
EventButton child = new EventButton(this);
child.setText("I am a child");
child.setBackgroundColor(Color.WHITE);
LayoutParams param = new LayoutParams(50, 50);
param.setMargins(10, 10, 10, 10);
child.setLayoutParams(param);
viewGroup.addView(child);
}
}
总结:
1、View事件传递
1)dispatchTouchEvent,分发事件,onTouchEvent返回true,它就返回true。如果action_down事件返回false,那么后续的事 件如action_move、action_up等将不会得到处理。
2)onTouchEvent,如果action_down事件返回false,那么后续的事件如action_move、action_up等将不会得到处理。
2、ViewGroup事件传递
1)dispatchTouchEvent:与View类似。
2)onInterceptTouchEvent:默认返回false,表示不拦截。子类需要重写这个方法。
3)
onTouchEvent:与View类似。
3、ViewGroup里面包含子View的事件传递
设viewGroup里面包含了一个子view,名为child。首先是viewGroup先收到事件。dispatchTouchEvent首先处理,接着是onInterceptTouchEvent,若onInterceptTouchEvent返回true,那么此事件由viewGroup处理,接着会执行viewGroup的onTouchEvent,也就是被拦截了;若onInterceptTouchEvent返回false,那么此事件将会交由viewGroup的子view进行处理,view的
dispatchTouchEvent方法首先执行,然后是view的onTouchEvent方法被执行。
此时,重点来了。
若onTouchEvent方法返回false,那么down事件就到了viewGroup,若viewGroup的ontouchEvent返回true,那么后续事件都将由viewGroup处理;若返回false,那么后续事件将不会得到处理。
若onTouchEvent方法返回true,那么接下来的move、up等事件都交由view处理。
此时viewGroup将会对move事件进行拦截,若onInterceptTouchEvent返回false,那么view将完全代理所有事件;若返回true,那么将强制发送cancel事件给view,move事件和up事件将由viewGroup进行处理。
手绘图一张: