ViewGroup 继承View,实现了View各个方法,同时ViewGroup中包含了不同的View,事件消息在ViewGroup中的传递就比较重要了,理解了事件的传递,才能够写出符合需求的自定义的ViewGroup。
首先分析一下onInterceptTouchEvent函数,此函数是ViewGroup独有的拦截函数,顾名思义,是拦截用户触发的事件,来决定此事件是否要传递给子View。原理比较简单,但是传递流程稍许复杂。
先看一段官方的文档:
· You will receive the down event here.
· The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.
· For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
· If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.
看着头昏脑涨,在来一段中文的翻译:
由于onInterceptTouchEvent()的机制比较复杂,上面的说明写的也比较复杂,总结一下,基本的规则是:
1. down事件首先会传递到onInterceptTouchEvent()方法
2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。
这里重要一点是对down事件的处理,这里是决定消息是分发给子View还是自己处理的关键点。
demo1: layout以及子View onTouchEvent 返回true
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
// break;
return true;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
break;
// return true;
case MotionEvent.ACTION_UP:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");
break;
// return true;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
break;
}
return false;
}
在layout中拦截ACTION_DOWN,子类view不会收到任何消息,而是直接把消息分发给layout的OnToucheEvent处理
D/LayoutView2(15426): onInterceptTouchEvent action:ACTION_DOWN
D/LayoutView2(15426): onTouchEvent action:ACTION_DOWN
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15426): onTouchEvent action:ACTION_UP
Demo2:layout 拦截ACTION_MOVE layout以及子View onTouchEvent 返回true
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
break;
// return true;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
// break;
return true;
case MotionEvent.ACTION_UP:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");
break;
// return true;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
break;
}
return false;
}
layout的消息传递:
D/LayoutView2(15765): onInterceptTouchEvent action:ACTION_DOWN
D/LayoutView2(15765): onInterceptTouchEvent action:ACTION_MOVE
D/LayoutView2(15765): onTouchEvent action:ACTION_MOVE
D/LayoutView2(15765): onTouchEvent action:ACTION_UP
也就是当 action:ACTION_MOVE被拦截时,action:ACTION_MOVE后续的消息直接传递给onTouchEvent
子View的消息传递为:
D/MyTextView(15765): onTouchEvent action:ACTION_DOWN
D/MyTextView(15765): onTouchEvent action:ACTION_CANCEL (这个消息一直没有弄明白)
Demo3:layout 拦截ACTION_MOVE layout onTouchEvent 返回true 子View的onTouchEvent返回false
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
break;
// return true;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
break;
// return true;
case MotionEvent.ACTION_UP:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");
break;
// return true;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
break;
}
return false;
}
layout的消息传递:
D/LayoutView2(16536): onInterceptTouchEvent action:ACTION_DOWN
D/LayoutView2(16536): onTouchEvent action:ACTION_DOWN
D/LayoutView2(16536): onTouchEvent action:ACTION_MOVE
D/LayoutView2(16536): onTouchEvent action:ACTION_UP
子View消息传递:
D/MyTextView(16536): onTouchEvent action:ACTION_DOWN
这里消息向下拦截的逻辑,当onInterceptTouchEvent拦截了ACTION_MOVE后,ACTION_MOVE后的消息就不在分发给子View,而是分发给layout的OnTouchEvent。
如果Layout的onInterceptTouchEvent对ACTION_DOWN消息没有拦截,但是子View的OntouchEvent不处理这些消息,仍会返回Layout的OnTouchEvent,如果Layout的OnTouchEvent对ACTION_DOWN消息进行了处理,后续的消息就会直接发送到Layout的OnTouchEvent。
分享到:
相关推荐
总的来说,`onInterceptTouchEvent`和`onTouchEvent`是Android事件处理中的重要组成部分,它们决定了触摸事件在View和ViewGroup间的分发。理解和熟练运用这两个方法,可以极大地提高Android应用的用户体验,尤其是...
对于ViewGroup,如果事件被拦截(`onInterceptTouchEvent`返回`true`),那么事件会在`onTouchEvent`中处理;对于View,事件总是会到达`onTouchEvent`,除非在父视图中被拦截。 在`onTouchEvent`中,ACTION_DOWN...
`onInterceptTouchEvent`和`onTouchEvent`是两个核心的方法,它们共同决定了Android应用如何响应用户的触摸操作。这两个方法主要在ViewGroup(如布局)和View(如按钮、文本框等)中被使用。 首先,我们来理解`...
对于ViewGroup而言,只有在其`onInterceptTouchEvent`返回`true`的情况下,才会调用`onTouchEvent`来处理事件。 3. 触摸事件序列:触摸事件通常包含一系列的动作,如`ACTION_DOWN`、`ACTION_MOVE`、`ACTION_UP`等。...
`onInterceptTouchEvent`和`onTouchEvent`是两个关键的方法,它们协同工作以处理触摸屏幕的动作。这篇文章将深入探讨这两个方法的调用关系及其在Android事件分发机制中的作用。 首先,我们要理解Android的事件分发...
在Android开发中,触摸事件处理是用户界面交互的关键部分,`onTouchEvent` 和 `onInterceptTouchEvent` 是处理这些事件的两个重要方法。本文将深入探讨这两个方法的使用、顺序以及它们在Android事件分发机制中的角色...
侧滑面板(对ViewGroup的自定义) * 应用场景: 扩展主面板的功能 ... 触摸优化: 重写ViewGroup里onInterceptTouchEvent和onTouchEvent Github 大牛 Jake Wharton nineoldandroids.jar 属性动画 ActionBarSherlock
`onTouchEvent`是`View`级别的事件处理,而`onInterceptTouchEvent`是`ViewGroup`级别的事件拦截。开发者可以灵活运用这两个方法来实现复杂的触摸交互,提高用户体验。理解它们的工作机制对于优化UI交互和提升应用的...
在自定义ViewGroup中,很多效果都包含用户手指去拖动其内部的某个View(eg:侧滑菜单等),针对具体的需要去写好onInterceptTouchEvent和onTouchEvent这两个方法是一件很不容易的事,需要自己去处理:多手指的处理、加...
`onInterceptTouchEvent`是Android中的一个方法,它属于`ViewGroup`类,主要用于父视图(如布局)拦截子视图的触摸事件。当用户在屏幕上进行触控操作时,Android会按照一定的顺序分发触摸事件。如果父视图想要处理...
安卓事件分发机制测试代码,事件传递从Activity-->ViewGroup-->View。dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent这三个函数的返回值不同,代表的事件传递的不同。
在自定义ViewGroup中,很多效果都包含用户手指去拖动其内部的某个View(eg:侧滑菜单等),针对具体的需要去写好onInterceptTouchEvent和onTouchEvent这两个方法是一件很不容易的事,需要自己去处理:多手指的处理、加...
事件拦截机制主要涉及两个关键方法:ViewGroup的`onInterceptTouchEvent`和View的`onTouchEvent`。当一个触摸事件发生时,系统首先调用ViewGroup的`onInterceptTouchEvent`,如果返回true,表示ViewGroup拦截了事件...
这样,你可以重写onInterceptTouchEvent和onTouchEvent方法,来处理触摸事件,使得每个ListView只响应自己的滚动事件,而ScrollView则处理垂直方向的总滚动。 在项目中,DListView可能是一个自定义的ListView实现,...
2. **使用ViewGroups的onInterceptTouchEvent和onTouchEvent方法**:如果你无法或不想使用NestedScrollView,可以通过重写父ScrollView的onInterceptTouchEvent和onTouchEvent方法来实现自定义的滚动行为。...
- `onTouchEvent(MotionEvent ev)`:当事件未被`ViewGroup`拦截时,会到达子`View`的`onTouchEvent()`,在这里处理具体的事件逻辑。 4. **事件顺序** 事件分发遵循以下顺序:`dispatchTouchEvent()` -> `...
Android中的事件分发分为三步:dispatchTouchEvent()、onInterceptTouchEvent()和onTouchEvent()。当一个触摸事件发生时,它会从Activity开始,通过ViewGroup层层向下分发到具体的子View。 1. dispatchTouchEvent()...
事件处理的顺序是:`onTouchEvent()` -> `onInterceptTouchEvent()` -> `onTouchEvent()`。在`onTouchEvent()`中,我们可以根据滑动方向和速度来计算`ListView`的移动距离,然后更新它们的位置。同时,需要处理滑动...