事件分发

1.触摸事件的ACTION
ACTION_DOWN:手指触摸屏幕最早触发一个ACTION
ACTION_MOVE:
ACTION_UP:

2.触摸事件涉及到的控件类型:
Activity:最先获取到触摸事件的控件
ViewGroup:容器控件(Relativilayout,LinearLayout等)
子view:不能放置控件的控件(TextView,Button等)

3.触摸事件的传递方向:
Activity==》ViewGroup==》子view==》ViewGroup==>Activity

4.触摸事件传递时涉及到的方法:
dispatchTouchEvent:事件分发,具有事件分发和消费的功能

onInterceptTouchEvent:事件拦截,具有事件拦截的功能,没有消费功能

onTouchEvent:事件响应,具有事件消费的功能

5.触摸事件返回值对事件的影响
dispatchTouchEvent:

true:会消费掉当前事件,事件将不会继续向下传递

false:不会消费当前事件,并且会将当前事件分发到上一层控件的onTouchEvent中

super:按照默认情况走完整个流程(具体控件,具体分析)

onInterceptTouchEvent:

true:会拦截所有子控件的事件,并且直接传递到自己的onTouchEvent中

false:按照默认情况走完整个流程(不会对事件的走向产生影响)

super:按照默认情况走完整个流程(具体控件,具体分析)

onTouchEvent:

true:会消费掉当前事件,事件将不会继续向下传递

false:按照默认情况走完整个流程(不会对事件的走向产生影响)

super:按照默认情况走完整个流程(具体控件,具体分析)




还是以自定义的TestButton为例。

我们可以通过重写onTouchEvent方法来处理诸如down move up的消息:

public class TestButton extends Button {  
  
    public TestButton(Context context) {  
        super(context);  
        // TODO Auto-generated constructor stub  
    }  
      
    public TestButton(Context context, AttributeSet attributeSet) {  
        super(context, attributeSet);  
        // TODO Auto-generated constructor stub  
    }  
      
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        boolean value = super.onTouchEvent(event);  
        System.out.println("super.onTouchEvent: " + value+ " event: " + event.getAction());  
        return value;  
    } 

 

也可以通过实现OnTouchListener的接口,然后设置TestButton的onTouchListener可以达到同样的目的
  class OnTouchListenerTest implements View.OnTouchListener{  
@Override  
public boolean onTouch(View v, MotionEvent event) {  
    return false;  
}  
      
  }  

TestButton b = (TestButton)findViewById(R.id.button);  
OnTouchListenerTest listener = new OnTouchListenerTest();  
b.setOnTouchListener(listener);  


但上述两种监听有什么区别呢?

先看一下Android源码中对于View中dispatchTouchEvent的实现:

public boolean dispatchTouchEvent(MotionEvent event){  
    ... ...  
    if(onFilterTouchEventForSecurity(event)){  
        ListenerInfo li = mListenerInfo;  
        if(li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED  
            && li.mOnTouchListener.onTouch(this, event)) {  
            return true;  
        }  
        if(onTouchEvent(event)){  
            return true;  
        }  
    }  
    ... ...  
    return false;  
}  


可以看到onTouchListener的接口的优先级是要高于onTouchEvent的,假若onTouchListener中的onTouch方法返回true,

表示此次事件已经被消费了,那onTouchEvent是接收不到消息的。

因为Button的performClick是利用onTouchEvent实现,假若onTouchEvent没有被调用到,那么Button的Click事件也无法响应。


综合来讲:

onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发。

假如onTouch方法返回false会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。

内置诸如click事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。




个人总结

    首先事件是从最外层的Activity传递过来,viewGroup会以此把事件遍历给每一个子控件、如果子控件也没有消费掉,则会,把事件依次返回
给父控件、最后传给Activity。

如果viewGroup的dispatchTouchEvent返回true,那么它就不会向下分发事件、会自己消费事件,viewGroup的dispatchTouchEvent的ACTION_UP会执行,事件止于viewGroup的dispatchTouchEvent,

如果viewGroup的dispatchTouchEvent返回false,它会向下分发事件,下面执行 onInterceptTouchEvent事件

    true:两个作用。1,拦截事件,事件不会传递给子控件,2、自己消费事件、会执行自己的onTouchEvent();
    false: 不会拦截事件、事件向子控件传递。

如果传递到子控件 子控件 onTouchEvent();返回true,则会消费掉事件。

如果给一个view设置了onTrouch()事件,这个onTouch事件 是先于onTouchEvent执行的,如果onTrouch()返回true,则不会,执行
onTouchEvent(),onClick()又是依赖于onTouchEvent(),所以onClick()也不会执行。只有onTrouch()返回false,才会执行
onTouchEvent,onTouchEvent(),返回true,才会执行view的onClick()事件。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值