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();
}
网友评论