SwipeRefreshLayout的事件处理
来源:互联网 发布:淘宝上的游侠9账号 编辑:程序博客网 时间:2024/05/23 23:09
本文并不是SwipeRefreshLayout全部事件处理的分析,而是针对一点进行详细的解析。具体是哪一点呢,不要着急,先听我说一个效果…
效果呢是这样:
- 最早的下拉刷新大概是github上的一个pulltorefresh的一个库,这种库下拉效果是这样的:ListView向上滚动(手指向下滑动),当滚动到第一条的时候继续滚动的话是没有任何效果的,这时必须手抬起,重新按下然后向下滑动,下拉刷新的头部才会出现
- SwipeRefreshLayout的效果是这样的,当滚动到第一条,手指不离开屏幕,继续向下滑动,这时下拉的头部就可以下拉出来了
有点绕,大家体会一下这个区别,不行自己拿demo跑一下看看。
可能看完上面的就有高手说话了,这还不简单,想和SwipeRefreshLayout一样的话直接在ListView的父布局中的onInterceptTouchEvent
方法中判断ListView是否滚动到最上面不就完了吗。
道理是这么个道理,那就实际操作一下试试吧,自定义一个类SwipeRefreshLayout1
,继承LinearLayout,复写onInterceptTouchEvent
方法:
public class SwipeRefreshLayout1 extends LinearLayout { public SwipeRefreshLayout1(Context context) { super(context); } public SwipeRefreshLayout1(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.e("lzw","onInterceptTouchEvent"); return super.onInterceptTouchEvent(ev); }}
布局文件是这样写的,就是在上面的自定义的布局中放了一个ListView,好了,下面拖动一下ListView试试吧
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.pulltorefresh.pulltorefreshviews.SwipeRefreshActivity"> <com.pulltorefresh.pulltorefreshviews.SwipeRefreshLayout1 android:layout_width="match_parent" android:layout_height="match_parent"> <com.pulltorefresh.pulltorefreshviews.ListView1 android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="wrap_content"></com.pulltorefresh.pulltorefreshviews.ListView1> </com.pulltorefresh.pulltorefreshviews.SwipeRefreshLayout1></RelativeLayout>
这是Log:,前面带---------
的是ListView的onTouchEvent
的Log。
08-17 02:54:38.621 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: onInterceptTouchEvent08-17 02:54:38.621 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: ---------onInterceptTouchEvent08-17 02:54:38.621 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: -------onTouchEvent08-17 02:54:38.730 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: onInterceptTouchEvent08-17 02:54:38.730 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: -------onTouchEvent08-17 02:54:38.741 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: onInterceptTouchEvent08-17 02:54:38.741 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: -------onTouchEvent08-17 02:54:38.761 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: onInterceptTouchEvent08-17 02:54:38.761 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: -------onTouchEvent08-17 02:54:38.800 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: -------onTouchEvent08-17 02:54:38.810 1532-1532/com.pulltorefresh.pulltorefreshviews E/lzw: -------onTouchEvent
仔细看一下Log就会发现我擦嘞,怎么有问题啊,SwipeRefreshLayout1
的onInterceptTouchEvent
方法怎么走了几次以后不走了啊,不按套路出牌啊,正常套路不应该是只要onInterceptTouchEvent
不拦截(不返回true)事件会一直从onInterceptTouchEvent
中走的啊(事件的分发可以参考我的事件分发的博客看一下),真是见了鬼了。
怎么样,是不是不实际操作不知道,实际写一下发现吓一跳呢,我当时到这之后简直要崩溃了,一时也没发现问题所在,酒吧问题搁置了。过了若干时间之后。。。具体是多久之后我也记不住了 = =,心里仍然很不爽啊,为啥SwipeRefreshLayout
可以呢,为啥我写的就有问题呢,翻 源 码 ,就不信搞不定,皇天不负有心人,让我找到原因了。。。
在ListView的onTouchEvent
方法中的MotionEvent.ACTION_MOVE
中调用了onTouchMove
,onTouchMove
中又调用了startScrollIfNeeded
,startScrollIfNeeded
中又有这么一段代码(真是九曲十八弯啊。。。):
final ViewParent parent = getParent();if (parent != null) { parent.requestDisallowInterceptTouchEvent(true);}
你大爷的啊,调用了父类的requestDisallowInterceptTouchEvent
方法不让父类拦截事件了,我们再去看看SwipeRefreshLayout
人家这个方法做了点什么:
@Override public void requestDisallowInterceptTouchEvent(boolean b) { // if this is a List < L or another view that doesn't support nested // scrolling, ignore this request so that the vertical scroll event // isn't stolen if ((android.os.Build.VERSION.SDK_INT < 21 && mTarget instanceof AbsListView) || (mTarget != null && !ViewCompat.isNestedScrollingEnabled(mTarget))) { // Nope. } else { super.requestDisallowInterceptTouchEvent(b); } }
注释我都没给你去,各位程序猿们看看。mTarget
是RecycleView中嵌套的View,对于ListView类型的子View,人家这个方法压根什么都没做,直接忽略了。另外还有一点简单说一下,版本小于21的才会忽略,那大于21的呢?21是5.0,对于5.0之后所有的View都有NestedScroll机制,压根就不用单独去考虑了。。。
到这问题的关键点就分析完了,把这段代码复制到SwipeRefreshLayout1
中试一下,问题解决。我们就可以做到上面说的在onInterceptTouchEvent
中判断事件是否需要被拦截了。
后面我们在用这个重新写一个简洁的DragTopLayout,不知道这个的童鞋可以单独去搜一下,git上有,但是写的比较复杂,也有一些很蛋疼的BUG
吐槽一下,从开始写到现在解决问题用了好久。。。
- SwipeRefreshLayout的事件处理
- CoordinatorLayout+ViewPager+SwipeRefreshLayout滑动事件冲突的处理
- SwipeRefreshLayout上下刷新与左右滑动事件冲突的处理
- 关于SwipeRefreshLayout的刷新事件
- 解决SwipeRefreshLayout左右滑动事件冲突的问题
- 解决SwipeRefreshLayout左右滑动事件冲突的问题
- 解决SwipeRefreshLayout左右滑动事件冲突的问题
- 解决使用`SwipeRefreshLayout`下拉刷新和左右滑动事件冲突的问题
- 处理继承的事件
- java的事件处理
- java的事件处理
- java的事件处理
- java的事件处理
- java的事件处理
- 事件的处理
- 鼠标事件的处理
- 事件的处理
- 按键事件的处理
- 寻找缺少的整数
- Android TextView两端对齐、文本两端对齐
- getopts的用法
- 查看Android设备的CPU架构信息
- MySQL+InnoDB semi-consitent read原理及实现分析
- SwipeRefreshLayout的事件处理
- c语言结构体内存模型及计算(转载)
- POJ3187 Backward Digit Sums
- SuperMap iObject常见问题解答集锦(四)
- 单例模式
- java命名规范
- 排列组合专题
- PyGobject(一百一十一)使用Pyinstaller打包成APP和EXE
- Java MD5加密算法