关于SwipeRefreshLayout 与listView 滑动冲突的问题
最近项目里用到了 SwipeRefreshLayout 来处理诸如 listView ,ExpandableListView 的下拉刷新,上拉加载更多。
我的项目用到了 https://github.com/nuptboyzhb/SuperSwipeRefreshLayout 里的SuperSwipeRefreshLayout . 感觉还不错。
观察源码我发现它监听了 listView ,ExpandableListView,ScrollView,以及RecylerView的滑动差不多就是判断这几个控件滑动到底部看是不是最后一个元素,如果是最后一个元素就出发加载更多的事件。
本人 为了 以上控件不要触发 加载更多的事件。于是耍了个小阴招,在listView 的外围 包裹了一层LinearLayout.这样就不会触发加载更多的事件了。(表问我干嘛不想触发加载更多,原因是因为数据是全加载,也不要问我为什么使用全加载,因为设计就是这么要求的。不要问我为什么设计要这么搞,我也不知道)
但是当页面编写完成以后,测试人员发来 测试报告如图:
这个问题实际上就是 经典的 滑动事件冲突问题,因为 本来 滑动展示 第一行数据的时候 触发了刷新,所以一直展示不出第一行。
当然如果SwipeRefreshLayout 直接包裹 ListView 是不会有这个问题。
解决方式 我特地搜索: 有人是 这么搞的,写了 一个继承 SwipeRefreshLayout 的子类,然后重写:
- @Override
- public void onScroll(AbsListView absListView, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
- View firstView = absListView.getChildAt(firstVisibleItem);
- // 当firstVisibleItem是第0位。如果firstView==null说明列表为空,需要刷新;或者top==0说明已经到达列表顶部, 也需要刷新
- if (firstVisibleItem == 0 && (firstView == null || firstView.getTop() == 0)) {
- mSwipeView.setEnabled(true);
- } else {
- mSwipeView.setEnabled(false);
- }
- if (null != mOnScrollListener) {
- mOnScrollListener.onScroll(absListView, firstVisibleItem,
- visibleItemCount, totalItemCount);
- }
- }
代码是对的 但是 写个子类 有点花不来。
于是我思考与测试发现。如果 listView 先往上刷动 在往下滑动 时,listView 是可以相应这个滚动的事件的。
于是 有了个更直接的 办法,就是 监听 listView 的滑动代码如下:
- huiYuanListView.setOnScrollListener(new AbsListView.OnScrollListener() {
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- }
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- View firstView = view.getChildAt(firstVisibleItem);
- if(firstVisibleItem ==0 && (firstView == null || firstView.getTop() == 0))
- {
- swipe_refresh.setEnabled(true);
- LogUtils.d("滑动","true");
- }
- else
- {
- swipe_refresh.setEnabled(false);
- LogUtils.d("滑动","false");
- }
- }
- });
意思就是只要 listView 向上滑动 ,看后面的数据 我就 设置 SwipeRefreshLayout 不可用,这样 listView 向上滑动看前面的数据 就不会触发SwipeRefreshLayout 的刷新事件的。
只有当listView 滑动到顶部 再将SwipeRefreshLayout 设置为可用。让它可以触发刷新。
最后 说下 通常 SwipeRefreshLayout 应该要包裹一个 可以滑动的 控件,且是一个控件,并不应当 包裹两个可滑动的控件,或者一个没有滑动事件的 ViewGroup.
如果包裹一个不带滑动的ViewGroup 就会引发 滑动冲突的问题。