当我们在布局的时候,很容易在ViewGroup下嵌套一个View或者ViewGroup,这时候就很容易产生事件的冲突,这里以Touch事件为例,为大家演示下,Android里事件的传递机制。
这里创建3个类,Example04Activity,ExampleView01,ExampleView02分别继承Activity,LinearLayout,ListView,正好是3种不同的。
Example04Activity的布局非常简单,就是LinearLayout套个ListView,这里主要讲解事件的传递机制,其他就不过多介绍。
3个类都实现onTouchEvent 方法。
Example04Activity:
public class Example04Activity extends Activity{
private ExampleView01 preContent=null;
private ExampleView02 lvContent=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity06);
initView();
initContent();
}
public void initView(){
preContent=(ExampleView01)findViewById(R.id.scview1);
lvContent=(ExampleView02)findViewById(R.id.list1);
}
public void initContent(){
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("sss", "activity touch");
return super.onTouchEvent(event);
}
}
ExampleView01:
public class ExampleView01 extends LinearLayout{
public ExampleView01(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("sss", "ViewGroup touch");
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("sss", "ViewGroup Intercept ");
return super.onInterceptTouchEvent(ev);
}
}
ExapleView02:
public class ExampleView02 extends ListView{
public ExampleView02(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExampleView02(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("sss", "View touch");
return super.onTouchEvent(event);
}
}
上面仅仅是重写了onTouchEvent onInterceptTouchEvent等方法,但是都未进行修改,也就是说,现在在logcat打印的结果,就是android,事件传递机制。
仅仅在界面一点击
显示:
也就是说,先通过最外层的ViewGroup的onInterceptTouchEvent然后,再通过子View的onTouchEvent。
这是为什么呢?
首先简单介绍下,android的事件传递机制,然后再由显示结果来说明。
首先touch事件触发,被最外层的ViewGroup接收到,调用onInterceptTouchEvent方法,
若返回true,则说明这个事件被ViewGroup拦截了,不再向下也就是ViewGroup下的View或ViewGroup传递,而是直接调用ViewGroup的onTouchEvent。
我们把onInterceptTouchEvent 的返回值直接改为true(代码这个事件拦截了)
代码:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("sss", "ViewGroup Intercept ");
return true;
}
其他不变。
点击,显示:
先调用onInterceptTouchEvent 在调用ViewGroup的onTouchEvent,不在调用了子View的onTouchEvent了,因为被拦截了。
现在我们总结下onInterceptTouchEvent 和onTouchEvent的作用。
onInterceptTouchEvent 是用于ViewGroup,从最外层的ViewGroup开始,一层一层调用(如果返回的都为false),一直往下抛,直到下面没有ViewGroup了,那么就调用最后一个View的onTouchEvent(如果返回的都为false),然后一层一层的往上抛,直到抛到最外面的activity。如果在某一个onInterceptTouchEvent 返回了true,那么就说明这个事件被拦截了,
就不在往下抛,如果onTouchEvent返回true,那么就代表,这个事件已经被这个View处理,就不再往上抛。