SwiperefreshLayout in Android

后端 未结 7 2118
半阙折子戏
半阙折子戏 2020-12-09 03:58

i am using SwipeRefreshLayout in my below layout:




        
相关标签:
7条回答
  • 2020-12-09 04:26

    I would say it's better to have an extended SwipeRefreshLayout with listener to be able to add various conditions from the classes that display this layout.

    Something like the following: GeneralSwipeRefreshLayout.java

    public class GeneralSwipeRefreshLayout extends SwipeRefreshLayout {   
      private OnChildScrollUpListener mScrollListenerNeeded;
    
      public interface OnChildScrollUpListener {
        boolean canChildScrollUp();
      }
    
      public GeneralSwipeRefreshLayout(Context context) {
        super(context);   
      }
      public GeneralSwipeRefreshLayout(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();
      }
    }
    

    And then inside your class that displays SwipeRefreshLayout containing ListView or GridView layout, you can do something like this:

    mSwipeLayout.setOnChildScrollUpListener(new OnChildScrollUpListener() {
      @Override
      public boolean canChildScrollUp() {
        return mListView.getFirstVisiblePosition() > 0 || 
               mListView.getChildAt(0) == null || 
               mListView.getChildAt(0).getTop() < 0;
      }
    });
    
    0 讨论(0)
  • 2020-12-09 04:28

    As others have already stated, if you don't have your scrollable view (ie listview) as the direct child of the SwipeRefreshLayout, the stock canChildScrollUp will not work.

    Has to do with the simple logic SwipeRefreshLayout uses in checking the ability of the child view to scroll.

    I was using a ListView inside an ActionbarActivity, and wanted to include an empty view whenever my listview was empty. This caused problems, since the SwipeRefreshLayout class can only have a single child. Note it also checks this child's ability to scrollUp to determine if a pull down causes the child to scrollUp, or if it causes the childs content to refresh.

    So if you want to use the same logic as SwipeRefreshLayout, just extend the class, and create a method to allow you to pass in the handle to your scrollable view. Note the stock implementation uses canScrollVertically() which does exactly what we want, but only appears in SDK >= 14.

    Also don't forget to include the constructor that contains the param "AttributeSet", when you extend the class, otherwise you will have problems using the class in your layout files.

    So, in the onCreate method of your Activity (in my case it was an ActionBarActivity) that includes the list view, just call setMyScrollableView passing in your ListView or whatever view you use that scrolls.

    /*Constructor*/
    public MySwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }
    
    
     View mMyScrollableView = null;  //The content that get's pulled down.
     /*Method used to pass in my scrollable view*/
     public void setMyScrollableView(View view){
        mMyScrollableView = view;
     }
    
    /**
     * @return Whether it is possible for the child view of this layout to
     * scroll up.  This was taken for the most part directly from SwipeRefreshLayout
     */
    public boolean canChildScrollUp() {
        if(mMyScrollableView == null)
          return false;
        if (android.os.Build.VERSION.SDK_INT < 14) {
            if (mMyScrollableView instanceof AbsListView) {
                final AbsListView absListView = (AbsListView) mMyScrollableView;
                return absListView.getChildCount() > 0
            && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
            .getTop() < absListView.getPaddingTop());
            } else {
                return mMyScrollableView.getScrollY() > 0;
            }
        } else {
            return ViewCompat.canScrollVertically(mMyScrollableView, -1);
        }
    }
    
    0 讨论(0)
  • 2020-12-09 04:37

    Just create a class which extends SwipeRefreshLayout and override the method canChildScrollUp(). Return true when you want scroll down for your control.

    For example for scrollview you may try this,

    @override.
    boolean canChildScrollUp()
    {
       //your condition to check scrollview reached at top while scrolling
       if(scrollview.getScrollY() == 0.0)
          return true;
       else
          return false;
    }
    
    0 讨论(0)
  • 2020-12-09 04:37

    I also found the other answers didn't quite work.

    Took me a while of head scratching to figure out that they are using the method getScrollY() which as this answer explains, is a View method describing how far it's been scroll within a container, not a method to describe how much your Scroll container has been scrolled.

    If you use the same technique as in the other answers (overriding the canChildScrollUp() method) you can easily check if the Scrollable is at it's highest point:

    @Override
    public boolean canChildScrollUp() {
        return !isListAtTop();
    }
    
    private boolean isListAtTop()   {   
        if(mGridView.getChildCount() == 0) return true;
        return mGridView.getChildAt(0).getTop() == 0;
    }
    

    (As you can see, I'm using a GridView, but you can use a ListView too)

    0 讨论(0)
  • 2020-12-09 04:42

    Easier solution is to use onScrollListener and check if user can see firstElement.

    someView.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView absListView, int scrollState) {
            if (scrollState == SCROLL_STATE_IDLE) {
                if (isViewAtTop()) {
                    swipeLayout.setEnabled(true);
                } else {
                    swipeLayout.setEnabled(false);
                }
            }
    
        }
    
        @Override
        public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (firstVisibleItem == 0) {
                swipeLayout.setEnabled(true);
            } else {
                swipeLayout.setEnabled(false);
            }
        }
    });
    

    Where method isViewAtTop() is some other method, that checks this View is scrolled to the top

    0 讨论(0)
  • 2020-12-09 04:44

    The solution from @User22791 works perfectly and, based on that, I created a library available on github that you can use (and modify) for make the usage of swipeRefreshLayout easier for developers. It's here: https://github.com/dagova/referencedSwipeRefreshLayout

    Basically you just have to reference in your layout the view to be checked in the method canChildScrollUp. I hope it will be useful.

    0 讨论(0)
提交回复
热议问题