本次测试采用的是外层ScrollView,内层ListView,(注:ListView显示不全的问题不在本次讨论范围)
布局为:

<?xml version="1.0" encoding="utf-8"?>                                                                                

3个TextView是为了让ScrollView可以滚动

自定义MyListView继承自ListView

MyListView:

package a453826252.github.intercom.view;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.ListView;public class MyListView extends ListView {    public MyListView(Context context) {        super(context);    }    public MyListView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    //这个是重点///    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        if(ev.getAction() == MotionEvent.ACTION_DOWN){            getParent().requestDisallowInterceptTouchEvent(true);        }        return super.dispatchTouchEvent(ev);    }}

当调用了dispatchTouchEvent(MotionEvent ev)说明事件已经传到了这个view

1、

ACTION_DOWN事件传到本view时,说明后面还有0-n个ACTION_MOVE事件和一个ACTION_UP事件,因为这是一个完整的事件序列(事件序列:从ACTION_DOWN开始,伴随0或多个ACTION_MOVE事件,以ACTION_UP事件结束)

2、

本view接收到ACTION_DOWN事件后,告知父容器View接下来的事件序列不要拦截(getParent().requestDisallowInterceptTouchEvent(true);)这样,后面的事件,本View都能接收到
然后调用父View的dispatchTouchEvent(ev)方法,该拦截拦截,该传递传递(在本View内部,注意父View父容器View的区别)

3、

若本View的子view(这时,本View作为父容器View)不需要事件,即:事件只传递本View,不在继续分发,则上面的代码中的dispatchTouchEvent(MotionEvent ev)可以改成:

//这个是重点///    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        if(ev.getAction() == MotionEvent.ACTION_DOWN){            getParent().requestDisallowInterceptTouchEvent(true);        }        return onTouchEvent(ev); //这句改变,直接调用本view的onTouchEvent(ev)方法    }

因为dispatchTouchEvent(MotionEvent ev)中有事件分发的逻辑,在里面判断需要拦截时才会调用onTouchEvent方法,而我们已经知道了,子View不需要事件,因此可以直接调用,省去判断是否拦截的逻辑。

4、

根据第三步,代码也可以改为:

//这个是重点/// @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        if(ev.getAction() == MotionEvent.ACTION_DOWN){            getParent().requestDisallowInterceptTouchEvent(true);        }        return super.dispatchTouchEvent(ev);    }//这个是重点///@Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        return true;    }

理由同第三条,直接拦截

推荐:
当子元素占满父元素空间时,使用外部拦截法
当没有占满时使用内部拦截



作者:阿泰2019
链接:https://www.jianshu.com/p/fbe71ca13244
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

更多相关文章

  1. 【Android】Android(安卓)Input
  2. Android实现点击事件的三种方法
  3. android eventBus 的简单使用(一)
  4. Android培训班(14)
  5. Android(安卓)Input Framework(三)---InputReader&InputDispatch
  6. Android(安卓)DataBinding 双向数据绑定、事件绑定、使用类方法
  7. android 比较有用的方法总结
  8. android中的alertdialog及LayoutInflater
  9. android:viewpager实现图片循环滑动+索引点击事件

随机推荐

  1. Android - 手机开发调试无法输出logcat信
  2. Android Studio 运行java程序
  3. Android 搜索 把软键盘上的回车键改为搜
  4. Android笔试的一部分知识点
  5. Android通信方式篇(四)-Binder机制(开篇)
  6. Android之网络请求8————OkHttp源码5:
  7. [Android] AsyncTask使用实例---加载网络
  8. Android中ContentProvider简介
  9. Android TextView中文字通过SpannableStr
  10. android ImageView图片缩放