【问题标题】:SwipeRefreshLayout loader not going up when pull down android下拉android时SwipeRefreshLayout加载器不会上升
【发布时间】:2016-01-30 11:22:51
【问题描述】:

我已经将 SwipeRefreshLayout 与 recyclerview 一起使用,它在所有 android 版本中都可以正常工作,但在 Kitkat 中,当我下拉时,SwipeRefreshLayout 加载器不会启动,也不会刷新 recyclerview 数据,但在棒棒糖中工作

我正在使用'com.android.support:support-v4:22.2.1'

编辑 1

SwipeRefreshLayout swipe_refresh;
swipe_refresh = (SwipeRefreshLayout)rootView.findViewById(R.id.swipe_refresh);

swipe_refresh.post(new Runnable() {
            @Override
            public void run() {
                swipe_refresh.setRefreshing(true);
            }
        });


swipe_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                // Loading more data..
                .....
                ....
                getData();

            }
        });

swipe_refresh.setColorSchemeResources(android.R.color.holo_blue_bright,
                android.R.color.holo_green_light,
                android.R.color.holo_orange_light,
                android.R.color.holo_red_light);

public void getData(){
    // Load data from web service...
    ...
    ...
    ...


    // After loading
    swipe_refresh.setRefreshing(false);

    // Set data to adapter
}

布局代码

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_refresh"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@color/grey_100">

     <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/gv_feeds"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="9"
                android:scrollbars="vertical"/>

            <ProgressBar
            android:id="@+id/prog_load_more"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_gravity="center_horizontal"
            android:visibility="gone"/>

            </LinearLayout>

        </FrameLayout>

</android.support.v4.widget.SwipeRefreshLayout>

【问题讨论】:

  • 你调用swipeRefreshLayout.setRefreshing(false);加载数据何时完成?
  • 是的,我是……当我再次下拉刷新然后卡在屏幕上时,我可以通过拖动将其拉起……
  • 能否附上代码?
  • 代码好像没问题。即使请求失败,你也会调用 setRefreshing(false) 吗?
  • 现在有同样的问题。你能找到解决办法吗?

标签: android android-recyclerview swiperefreshlayout


【解决方案1】:

我之前也遇到过同样的问题。当您没有将 RecyclerView 作为 SwipeRefreshLayout 的直接子级时,似乎会发生这种情况。

我们通过使用像这样的自定义 SwipeRefreshLayout 解决了这个问题:

public class FixedSwipeRefreshLayout extends SwipeRefreshLayout {

    private RecyclerView recyclerView;

    public FixedSwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FixedSwipeRefreshLayout(Context context) {
        super(context);
    }

    public void setRecyclerView(RecyclerView recyclerView) {
        this.recyclerView = recyclerView;
    }

    @Override
    public boolean canChildScrollUp() {
        if (recyclerView!=null) {
            return recyclerView.canScrollVertically(-1);
        }

        return false;
    }

}

然后,不要使用android.support.v4.widget.SwipeRefreshLayout,而是使用您自己的“com.example.app.FixedSwipeRefreshLayout”,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<com.example.app.FixedSwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_refresh"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
...
</com.example.app.FixedSwipeRefreshLayout>

最后,当您获得 SwipeRefreshLayout 的句柄时,使用您自定义的句柄并设置您的 RecyclerView:

FixedSwipeRefreshLayout swipe_refresh;
swipe_refresh = (FixedSwipeRefreshLayout) rootView.findViewById(R.id.swipe_refresh);
RecyclerView mRecyclerView = (RecyclerView) rootView.findViewById(R.id.gv_feeds);
swipe_refresh.setRecyclerView(mRecyclerView);

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    根据 swipeRefreshDocumentation SwipeRefreshLayout 不能很好地与如果添加在其中不可滚动的布局一起使用: 你有两个解决方案:

    1) 更改布局以使 swipeRefreshLayout 具有直接子元素作为 recyclerView 。

    类似这样的:

    <?xml version="1.0" encoding="utf-8"?>
    
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical" android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:id="@+id/ll_HeaderProgress"
            android:background="@color/white_color_30">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
                <android.support.v4.widget.SwipeRefreshLayout
                    xmlns:android="http://schemas.android.com/apk/res/android"
                    android:id="@+id/swipe_refresh"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_weight="9"
                   >
                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerview_buzz"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scrollbars="vertical"/>
    </android.support.v4.widget.SwipeRefreshLayout>
                <ProgressBar
                    android:id="@+id/ll_footerProgress"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_gravity="center_horizontal"
                    android:visibility="gone"/>
            </LinearLayout>
        </FrameLayout>
    

    2) 使用监听器扩展 SwipeRefreshLayout,以便能够从显示此布局的类中添加各种条件。

    类似于以下内容:RefreshSwipeRefreshLayout.java

    public class RefreshSwipeRefreshLayout extends SwipeRefreshLayout {   
      private OnChildScrollUpListener mScrollListenerNeeded;
    
      public interface OnChildScrollUpListener {
        boolean canChildScrollUp();
      }
    
      public RefreshSwipeRefreshLayout(Context context) {
        super(context);   
      }
      public RefreshSwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);   
      }
    
     /**
      * Listener that controls if scrolling up is allowed to child views or not
      */
      public void setOnChildScrollUpListener(OnChildScrollUpListener listener) {
        mScrollListenerNeeded = listener;   
      }
    
      @Override
      public boolean canChildScrollUp() {
        if (mScrollListenerNeeded == null) {
          Log.e(GeneralSwipeRefreshLayout.class.getSimpleName(), "listener is not defined!");
        }
        return mScrollListenerNeeded != null && mScrollListenerNeeded.canChildScrollUp();
      }
    }
    

    然后在显示 SwipeRefreshLayout 包含 recyclerView 布局的类中执行此操作,您可以执行以下操作:

    mSwipeLayout.setOnChildScrollUpListener(new OnChildScrollUpListener() {
      @Override
      public boolean canChildScrollUp() {
        return   ((LinearLayoutManager)mRecyclerView.getLayoutManager()).findFirstVisibleItemPosition().getFirstVisiblePosition() > 0 || 
               mRecyclerView.getChildAt(0) == null || 
               mRecyclerView.getChildAt(0).getTop() < 0;
      }
    

    });

    别忘了在xml里改一下

    【讨论】:

      【解决方案3】:

      你试试这个方法

         listView.setOnScrollListener(new OnScrollListener() {
      
          @Override
          public void onScrollStateChanged(AbsListView view, int scrollState) {
          }
      
          @Override
          public void onScroll(AbsListView view, int firstVisibleItem,
                  int visibleItemCount, int totalItemCount) {
              boolean enable = false;
              if(listView != null && listView.getChildCount() > 0){
                  // check if the first item of the list is visible
                  boolean firstItemVisible = listView.getFirstVisiblePosition() == 0;
                  // check if the top of the first item is visible
                  boolean topOfFirstItemVisible = listView.getChildAt(0).getTop() == 0;
                  // enabling or disabling the refresh layout
                  enable = firstItemVisible && topOfFirstItemVisible;
              }
              swipeRefreshLayout.setEnabled(enable);
          }});
      

      【讨论】:

        【解决方案4】:

        我可能会迟到回答这个问题,但我遇到了同样的问题,我所做的只是补充:

        swipe_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                // Loading more data..
                .....
                ....
                getData();
        
                //make sure to set it to false as this will be set it to true when onRefresh is triggered
                swipe_refresh.setRefreshing(false);
            }
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-02
          • 2010-10-14
          • 1970-01-01
          • 2013-10-24
          相关资源
          最近更新 更多