请简要描述一下事件分发机制,并说明onInterceptTouchEvent和onTouchEvent的作用和关系
Android的事件分发机制也是View和ViewGroup的事件的分发和处理,当用户手指接触到屏幕以后,所产生的一系列事件中,都被android包装成MotionEvent,由三种事件类型组成,ACTION_DOWN,ACTION_MOVE,ACTION_UP,
顺序是activity,再到viewGroup,再传递到View
由三种方法dispatchTouchEvent(),onInterceptTouchEvent,onTouchEvent所处理,dispatchTouchEvent的作用是分发传递点击事件,当点击事件能够传递给当前的View的时候,该方法都会被调用,onInterceptTouchEvent的作用是拦截事件,只存在ViewGroup中,在ViewGroup的dispatchTouchEvent中调用,如果onInterceptTouchEvent return true那么事件不会再传递下去,就让当前view的ontouchEvent来处理
onTouchEvent的作用的是处理点击事件
我们看一个例子:
public class EventTest extends Activity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.event_test); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: Log.d("TAG","<<<<<activity ontouch down"); break; case MotionEvent.ACTION_MOVE: Log.d("TAG","<<<<<activity action move"); break; case MotionEvent.ACTION_UP: Log.d("TAG","<<<<<activity action up"); break; } return false; } }
xml文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:fresco="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.pic.optimize.ParentView android:layout_width="match_parent" android:layout_height="match_parent"> <com.pic.optimize.ChildView android:layout_width="200dp" android:layout_height="200dp" android:background="#FF00FF" android:layout_centerInParent="true"/> </com.pic.optimize.ParentView> </RelativeLayout>
ParentView:
public class ParentView extends RelativeLayout { public ParentView(Context context, AttributeSet attrs) { super(context, attrs); } /** * 方法用户拦截被传递过来的事件,用于判断被传递过来的事件是否需要被当前的view进行处理 * return true : 拦截该事件,将该事件交给当前view的onTouchEvent方法进行处理 * return false和super.interceptTouchEvent(ev),事件将不会被拦截,会被分发到子控件中) */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return true; } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: Log.d("TAG","<<<<<ParentView ontouch down"); break; case MotionEvent.ACTION_MOVE: Log.d("TAG","<<<<<ParentView action move"); break; case MotionEvent.ACTION_UP: Log.d("TAG","<<<<<ParentView action up"); break; } return false; } }
运行结果是:
触摸蓝色的框的区域:
这个时候打印的结果是
<<<<<ParentView ontouch down
<<<<<activity ontouch down
<<<<<activity action move
<<<<<activity action up
public class ChildView extends View { public ChildView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } /** * 当前的view把事件进行了拦截,则事件则会被传递到该方法中 * return false:表明没有消费该事件,事件将会以冒泡的方式一直被传递到上层的view或Activity中的 * return true: 表明消费了该事件,事件到此结束。 * return super.onTouchEvent(event):默认情况,和return false一样。 */ @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: Log.d("TAG","<<<<<childview ontouch down"); break; case MotionEvent.ACTION_MOVE: Log.d("TAG","<<<<<ChildView action move"); break; case MotionEvent.ACTION_UP: Log.d("TAG","<<<<<ChildView action up"); break; } return true; } }
如果我们把parentView的onInterceptTouchEvent return false
那么childView的onTouchEvent return true,那么打印的结果是
<<<<<childview ontouch down
<<<<<ChildView action move
<<<<<ChildView action up
如果我们把childView的ontouchEvent return false
<<<<<childview ontouch down
<<<<<ParentView ontouch down
<<<<<activity ontouch down
<<<<<activity ontouch move
<<<<<activity ontouch up
共同学习,写下你的评论
评论加载中...
作者其他优质文章