美文网首页一席Android
SwipeRefreshLayout 自定义 canChildS

SwipeRefreshLayout 自定义 canChildS

作者: substarry | 来源:发表于2016-05-25 10:58 被阅读1531次

    SwipeRefreshLayout 是一个下拉属性控件,只需要将如ListView、RecyclerView等控件作为它的child view即可,它可以自己处理下拉事件,当child view可以下拉时,则优先滑动child view,当child view滑到顶部时,则触发SwipeRefreshLayout 的下拉刷新。

    但是当SwipeRefreshLayout 中包含多个child view时,则可能会失效,原因是SwipeRefreshLayout只会通过child view 中最上面的一个view来处理滑动事件。具体看源码:

        public boolean canChildScrollUp() {
            if (android.os.Build.VERSION.SDK_INT < 14) {
                if (mTarget instanceof AbsListView) {
                    final AbsListView absListView = (AbsListView) mTarget;
                    return absListView.getChildCount() > 0
                            && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                                    .getTop() < absListView.getPaddingTop());
                } else {
                    return ViewCompat.canScrollVertically(mTarget, -1) || mTarget.getScrollY() > 0;
                }
            } else {
                return ViewCompat.canScrollVertically(mTarget, -1);
            }
        }
    

    可以看到,SwipeRefreshLayout 是优先 mTraget 处理下拉事件的;那么 mTraget哪里定义的呢?

        private void ensureTarget() {
            // Don't bother getting the parent height if the parent hasn't been laid
            // out yet.
            if (mTarget == null) {
                for (int i = 0; i < getChildCount(); i++) {
                    View child = getChildAt(i);
                    if (!child.equals(mCircleView)) {
                        mTarget = child;
                        break;
                    }
                }
            }
        }
    

    从上面的代码可以发现,其实mTraget就是我们放到child view中的第一个View。所以如果我们child view中需要滑动的并不是第一个,那么就会滑动失效,解决方法就是自定一个View继承SwipeRefreshLayout ,同时重写 canChildScrollUp 方法即可。直接上代码:

        //实际需要滑动的child view
        private View mScrollUpChild;
        
        public void setScrollUpChild(View view) {
            mScrollUpChild = view;
        }
    
        @Override 
        public boolean canChildScrollUp() {
            if (mScrollUpChild != null) {
                if (android.os.Build.VERSION.SDK_INT < 14) {
                    if (mScrollUpChild instanceof AbsListView) {
                        final AbsListView absListView = (AbsListView) mScrollUpChild;
                        return absListView.getChildCount() > 0
                                && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                                .getTop() < absListView.getPaddingTop());
                    } else {
                        return ViewCompat.canScrollVertically(mScrollUpChild, -1) || mScrollUpChild.getScrollY() > 0;
                    }
                } else {
                    return ViewCompat.canScrollVertically(mScrollUpChild, -1);
                }
            }
            return super.canChildScrollUp();
        }
    

    相关文章

      网友评论

        本文标题:SwipeRefreshLayout 自定义 canChildS

        本文链接:https://www.haomeiwen.com/subject/uhctdttx.html