我在项目中使用StickyHeaderListview
来显示内容并刷新列表,我正在使用SwipeRefreshLayout
。
这里的问题是,当我尝试向上滚动列表时,它开始刷新列表,不允许查看以前的列表项。
我希望行为应该是这样的,只有当我到达第一个项目并且我尝试向上滚动时才会刷新列表,而不是每次向上滚动列表时都会刷新。
有人可以为此提供帮助吗?
P.S。为了实现SwipeRefreshLayout,我引用了this example
答案 0 :(得分:18)
使用StickyHeaderListview
作为SwipeRefreshLayout
的直接子项时,我遇到了同样的问题。 StickyHeaderListview
实际上是一个FrameLayout
包裹ListView
。正如 nitesh goel 所解释的那样,这会导致canChildScrollUp()
出现问题。根据 nitesh goel 的示例,这是CustomSwipeRefreshLayout
的完整版本,适用于我:
public class CustomSwipeRefreshLayout extends SwipeRefreshLayout {
/**
* A StickyListHeadersListView whose parent view is this SwipeRefreshLayout
*/
private StickyListHeadersListView mStickyListHeadersListView;
public CustomSwipeRefreshLayout(Context context) {
super(context);
}
public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setStickyListHeadersListView(StickyListHeadersListView stickyListHeadersListView) {
mStickyListHeadersListView = stickyListHeadersListView;
}
@Override
public boolean canChildScrollUp() {
if (mStickyListHeadersListView != null) {
// In order to scroll a StickyListHeadersListView up:
// Firstly, the wrapped ListView must have at least one item
return (mStickyListHeadersListView.getListChildCount() > 0) &&
// And then, the first visible item must not be the first item
((mStickyListHeadersListView.getFirstVisiblePosition() > 0) ||
// If the first visible item is the first item,
// (we've reached the first item)
// make sure that its top must not cross over the padding top of the wrapped ListView
(mStickyListHeadersListView.getListChildAt(0).getTop() < 0));
// If the wrapped ListView is empty or,
// the first item is located below the padding top of the wrapped ListView,
// we can allow performing refreshing now
} else {
// Fall back to default implementation
return super.canChildScrollUp();
}
}
}
答案 1 :(得分:3)
好的我已经开始工作了。如果SwipeRefreshLayout
是布局的根,并且ListView
深入到层次结构中(我已将ListView
放在RelativeLayout
内,而空TextView
})而不是SwipeRefreshLayout
的直接子项,它不会检测到正确地在列表视图上向上滑动。
您应创建一个自定义类,在SwipeRefreshLayout
canChildScrollUp()
并覆盖SwipRefreshLayout
方法
这是一个例子:
public class CustomSwipeRefreshLayout extends SwipeRefreshLayout{
private AbsListView view;
public CustomSwipeRefreshLayout(Context context) {
super(context);
}
public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setView(AbsListView view){
this.view=view;
}
@Override
public boolean canChildScrollUp() {
return view.getFirstVisiblePosition()!=0;
}
}
答案 2 :(得分:2)
我遇到了类似的问题,直接子应该是ScrollView(或ListView)的一个实例。 SwipeRefreshLayout仅考虑直接子项的滚动而不考虑该直接子项的子项。我设法通过使用两个SwipeRefreshLayouts来解决这个问题。
我在github上发布了代码。
答案 3 :(得分:1)
嗨,我想我做了一些普遍使用的东西:
public class CustomSwipeRefreshLayout extends SwipeRefreshLayout {
private View v;
public CustomSwipeRefreshLayout(Context context) {
super(context);
}
public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setView(View v) {
this.v = v;
}
@Override
public boolean canChildScrollUp() {
return this.v.canScrollVertically(-1);
}
}
使用该解决方案,在调用canChildScrollUp()之后,仅设置要在SwipeRefreshLayout内滚动的视图。像这样:
this.refreshLayout.setView(aView);
this.refreshLayout.canChildScrollUp();
我不经常测试它,但是如果我正确的话,它将适用于SwipeRefreshLayout中每个地方的每个视图(直接孩子或不直接)。
(对我来说是SwipeRefreshLayout =&gt; RelativeLayout =&gt; SrcollView =&gt; linearLayout)
答案 4 :(得分:0)
这是一个非常简单的解决方案:
list.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
int topRowVerticalPosition = (list == null || list.getChildCount() == 0) ?
0 : list.getChildAt(0).getTop();
swipeRefreshLayout.setEnabled((topRowVerticalPosition >= 0));
}
});
因此,如果您位于列表视图的顶部,则可以进行刷新。