在写自定义控件或者view的时候肯定会涉及到事件的分发,今天来记录下自己的学习经验。

首先我们要知道跟touch事件有关的方法有:

public boolean dispatchTouchEvent(MotionEvent ev);  public boolean onInterceptTouchEvent(MotionEvent ev); public boolean onTouchEvent(MotionEvent ev); 

dispatchTouchEvent()
用来分派事件。其中调用了onInterceptTouchEvent()和onTouchEvent(),一般不重写该方法。

onInterceptTouchEvent()
用来拦截事件。默认是:{return false;}表示不拦截该事件,事件将向下传递。若重写该方法,使其返回true,则表示拦截事件终止向下传递

onTouchEvent()
用来处理事件。返回true则表示该View能处理该事件,事件将被消费掉;返回false表示不能处理,则把事件继续向下分发,如果向下没有子view则向上返回上一级处理,以此类推继续返。

这里还有个 public boolean onTouch(View v, MotionEvent event) 方法要说明下:

onTouchEvent(MotionEvent ev)onTouch(View v, MotionEvent event) 都可以用来处理手势监听,他们的区别我们通过两个例子来了解:
1、

public class MyButton extends Button {      public MyButton(Context context) {          super(context);          // TODO Auto-generated constructor stub     }      public MyButton(Context context, AttributeSet attributeSet) {          super(context, attributeSet);          // TODO Auto-generated constructor stub     }      @Override      public boolean onTouchEvent(MotionEvent event) {           return super.onTouchEvent(event); ;      } 

2、

MyButton= (Button) findViewById(R.id.mybutton);        MyButton.setOnTouchListener(new OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                // TODO Auto-generated method stub                return false;            }        });

可以看到一个是在重写控件的时候重写的方法,一个是在Activity里面设置监听时调用的方法。
但是onTouchListener的onTouch方法优先级比onTouchEvent高,如果都设置的话onTouch会先触发。
假如onTouch方法返回false会接着触发onTouchEvent,反之如果返回true则onTouchEvent方法不会被调用。
诸如onclick事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。
他俩都可以监听手势操作。由于平时我们一般都会比较偏向重写onTouchEvent方法。所以这里就只拿onTouchEvent来说。

好了言归正传接着说上述三个方法,上述三个方法不同的类拥有的方法也不同:
1、Activity类拥有: dispatchTouchEvent(); onTouchEvent();
2、ViewGroup(继承自View,表示可以有子控件,如FrameLayout、Linearlayout、Listview这些): 三个方法都拥有。
3、View(普通的控件,没有子布局的,如Button、TextView): dispatchTouchEvent(); onTouchEvent();

现在用一个例子来具体说下过程:

A –> frameLayout
C –> LinearLayout
D –> TextView

现在开始点击D
图是自带的画图工具画的,希望大家凑合看下。。。

总得来说,当点击事件到底层View(一般是个ViewGroup)以后,就会调用这个ViewGroup的dispatchTouchEvent方法,如果这个ViewGroup拦截事件返回true(默认是返回false),则事件由此ViewGroup处理,如果此时ViewGroup的OnTouchListener被设置,则onTouch会被调用,否则onTouchEvent会被调用,如果都提供的话就是上面所说的onTouch优先级高会屏蔽掉onTouchEvent。反之如果ViewGroup的拦截事件返回false,则事件会传递给在他点击链上的子View,这个时候子View的dispatchTouchEvent被调用,到此为止事件就从底层View传递到它的上一层View了,接下来的和其底层View传过来的行为一致了,如此循环直到整个事件派发结束。如果一个点击事件的子View的onTouchEvent返回了false,其父的onTouchEvent也返回了false,所有的View都没去处理,则最终会由Activity来处理。

如果你看过我自定义view-SlideSwitch开源详解的就会发现public boolean onTouchEvent(MotionEvent event) 方法里面的第一句话 getParent().requestDisallowInterceptTouchEvent(true); 这句话出现的原因是当SlideSwitch放在ScrollView里面滑动的时候会和ScrollView的滑动产生冲突,所以这里我们需要在按住SlideSwitch滑动的时候屏蔽掉ScrollView的滑动。通过requestDisallowInterceptTouchEvent()我们可以对disallowIntercept的值进行修改。这里为什么这么修改,大家有兴趣可以查看下源码,这里就不给提供了。

更多相关文章

  1. Android(安卓)ObjectAnimator不调用onAnimationStart方法
  2. Cocos2d-x移植android加入震动效果
  3. android xutils 基本使用 方法
  4. android OkHttp3
  5. xposed框架的检测和反制
  6. 学习Android过程中的一些博客或工具收集
  7. android中延迟执行某个任务的几种处理方法
  8. Android(安卓)音乐播放器 下一曲 连续跳几首歌
  9. 使用百度地图SDK 这是之前版本 现在的sdk v2-1-2使用方法完全改

随机推荐

  1. Android中Bitmap、Drawable、byte[]转换
  2. Android 你的OnTouchEvent() 触屏事件的
  3. Android Animation动画详解
  4. Android 签名失败 Lint found fatal erro
  5. 编译Android平台以及SDK
  6. osg for android 学习之三:老外的步骤,包括
  7. Android判断某个Activity是否正在前台显
  8. Android Studio设置gradle代理
  9. 封装Android Volley请求工具
  10. android SQLiteDatabase源码解析