最近遇到 添加 ScrollView 之后 某些组件的 onTouchEvent() 没有响应,现在我们来解剖一下android 对于这种事件的处理和内部的传递机制。
1.ViewGroup代表可以包含子组件的类,例如我们的(LinearLayout、TableLayout、ScrollView);
2.ChildView 代表不能包含其他组件的类 ,例如我们的(Button、TextView、EditText);
对于 ViewGroup 有包含 onInterceptTouchEvent(MotionEvent event) 和onTouchEvent(MotionEvent event)
而且 ChildView 只包含了 onTouchEvent(MotionEvent event)
如果有疑问的话可以去看一下 Button 和 TextView 的 API 里面确实查不到 onInterceptTouchEvent(MotionEvent event)
===============================================================================
为了大家更好理解我制作成图片了。
需要用到的源代码 MainActivity.java myScroll.java(继承 ScrollView) myLayout.java(继承 LinearLayout) myText.java(继承 EditText) activity_main.xml(布局文件)
- //MainActivity.java
- package com.example.lab;
- import android.app.Activity;
- import android.os.Bundle;
- public class MainActivity extends Activity
- {
- <span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span>@Override
- <span style="white-space:pre"> </span>protected void onCreate(Bundle savedInstanceState)
- <span style="white-space:pre"> </span>{
- <span style="white-space:pre"> </span>super.onCreate(savedInstanceState);
- <span style="white-space:pre"> </span>setContentView(R.layout.activity_main);
- <span style="white-space:pre"> </span>}
- <span style="white-space:pre"> </span>
- }
- //myScroll.java
- package com.example.lab;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.widget.ScrollView;
- public class myScroll extends ScrollView
- {
- public myScroll(Context context)
- {
- super(context);
- }
- public myScroll(Context context, AttributeSet attrs)
- {
- super(context, attrs);
- }
- public myScroll(Context context, AttributeSet attrs, int defStyle)
- {
- super(context, attrs, defStyle);
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event)
- {
- boolean b = super.onInterceptTouchEvent(event);
- Log.e("Info","Return " + b + " From myScroll OnInterceptTouchEvent" + "---" + "GetActionEvent:" + event.getActionMasked());
- return b;
- }
- @Override
- public boolean onTouchEvent(MotionEvent event)
- {
- boolean b = super.onTouchEvent(event);
- Log.e("Info","Return " + b + " From myScroll OnTouchEvent" + "---" + "GetActionEvent:" + event.getActionMasked());
- return b;
- }
- }
- //myLayout.java
- package com.example.lab;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.widget.LinearLayout;
- public class myLayout extends LinearLayout
- {
- public myLayout(Context context)
- {
- super(context);
- }
- public myLayout(Context context, AttributeSet attrs)
- {
- super(context, attrs);
- }
- public boolean onInterceptTouchEvent (MotionEvent event)
- {
- boolean b = super.onInterceptTouchEvent(event);
- Log.e("Info","Return " + b + " From myLayout OnInterceptTouchEvent" + "---" + "GetActionEvent:" + event.getActionMasked());
- return b;
- }
- public boolean onTouchEvent(MotionEvent ev)
- {
- boolean b = super.onTouchEvent(ev);;
- Log.e("Info","Return " + b + " From myLayout OnTouchEvent" + "---" + "GetActionEvent:" + ev.getActionMasked());
- return b;
- }
- }
- //myText.java
- package com.example.lab;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.widget.EditText;
- public class myText extends EditText
- {
- public myText(Context context)
- {
- super(context);
- }
- public myText(Context context, AttributeSet attrs)
- {
- super(context, attrs);
- }
- public myText(Context context, AttributeSet attrs, int defStyle)
- {
- super(context, attrs, defStyle);
- }
- @Override
- public boolean onTouchEvent(MotionEvent event)
- {
- boolean b = super.onTouchEvent(event);
- Log.e("Info","Return " + b + " From myText OnTouchEvent" + "---" + "GetActionEvent:" + event.getActionMasked());
- return b;
- }
- }
- avtivity_main.xml
- <com.example.lab.myScroll xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <com.example.lab.myLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <com.example.lab.myText
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- </com.example.lab.myText>
- </com.example.lab.myLayout>
- </com.example.lab.myScroll>
创建一个包名为 com.example.lab 然后把文件放到对应的地方就可以了运行了。
===========================================================================
有了源码,来说一下机制吧。
上面的布局文件 scroll 在最外层 layout 在中间 最里面的 text 如下面 这张图片
当我们触发屏幕事件的时候(点击屏幕、手指在屏幕上移动) 事件的传播流程是这样的。
如果 onInterceptTouchEvent() 返回的是 false(说明事件会传递下去),这里可以把 onInterceptTouchEvent() 看成是守门人,当它返回 false 的时候,证明目前这个类的 onTouchEvent 不是用来处理这个事件的,事件继续向内传播,如果返回 true 则由本类的onTouchEvent 进行处理,并停止事件的传播
制作这张图,看起来可能会直观一点。
其实onInterceptTouchEvent() 就是判断事件,OntouchEvent()就是处理事件。