Scrollup在使用SwipeRefreshLayout的StickyListviewHeader中无效

时间:2014-04-14 06:57:00

标签: android swiperefreshlayout

我在项目中使用StickyHeaderListview来显示内容并刷新列表,我正在使用SwipeRefreshLayout。 这里的问题是,当我尝试向上滚动列表时,它开始刷新列表,不允许查看以前的列表项。

我希望行为应该是这样的,只有当我到达第一个项目并且我尝试向上滚动时才会刷新列表,而不是每次向上滚动列表时都会刷新。

有人可以为此提供帮助吗?

P.S。为了实现SwipeRefreshLayout,我引用了this example

5 个答案:

答案 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));                                           
    }                                                                                                           
});                                                                                                             

因此,如果您位于列表视图的顶部,则可以进行刷新。