Home » Android » android – SwipeRefreshLayout interfering with setOnScrollListener

android – SwipeRefreshLayout interfering with setOnScrollListener

Posted by: admin June 15, 2020 Leave a comment

Questions:

Everytime I scroll the list up or down I hide (or unhide) some views with OnScrollListener. Here is the code attached to my ListView.

lv.setOnScrollListener(new OnScrollListener() {

            private int mLastFirstVisibleItem;
            private boolean mIsScrollingUp = true;
            private LinearLayout ll = (LinearLayout) getActivity()
                    .findViewById(R.id.llSearchPlaces);

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                                 int visibleItemCount, int totalItemCount) {



                if (view.getId() == lv.getId()) {
                    final int currentFirstVisibleItem = lv
                            .getFirstVisiblePosition();
                    if (currentFirstVisibleItem > mLastFirstVisibleItem) {

                        if (mIsScrollingUp == true) {
                            mIsScrollingUp = false;
                             Log.i("a", "scrolling down...");

                            floatingActionButton.hide();

                            Animation animation = new TranslateAnimation(0, 0,
                                    0, 200);
                            animation.setDuration(300);
                            animation
                                    .setAnimationListener(new AnimationListener() {

                                        @Override
                                        public void onAnimationEnd(
                                                Animation animation) {
                                            ll.setVisibility(View.INVISIBLE);
                                        }

                                        @Override
                                        public void onAnimationRepeat(
                                                Animation animation) {
                                        }

                                        @Override
                                        public void onAnimationStart(
                                                Animation animation) {
                                        }
                                    });

                            ll.startAnimation(animation);
                        }

                    } else if (currentFirstVisibleItem < mLastFirstVisibleItem) {

                        if (mIsScrollingUp == false) {
                            mIsScrollingUp = true;
                            floatingActionButton.show();
                             Log.i("a", "scrolling up...");

                            Animation animation = new TranslateAnimation(0, 0,
                                    200, 0);
                            animation.setDuration(400);
                            animation
                                    .setAnimationListener(new AnimationListener() {

                                        @Override
                                        public void onAnimationEnd(
                                                Animation animation) {

                                        }

                                        @Override
                                        public void onAnimationRepeat(
                                                Animation animation) {

                                        }

                                        @Override
                                        public void onAnimationStart(
                                                Animation animation) {
                                            ll.setVisibility(View.VISIBLE);

                                        }
                                    });

                            ll.startAnimation(animation);

                        }
                    }

                    mLastFirstVisibleItem = currentFirstVisibleItem;

                }
            }
        });

Layout:

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/swipe_refresh_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ListView
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fadeScrollbars="true"
        android:listSelector="#00000000"
        android:scrollbars="none" />

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

Ever since I added the SwipeRefreshLayout, I do not get anything when I Log inside the listener above. How can I use both of these items together?

EDIT: It seems like this is what I need but I can’t make it work still

As part of that article I added this in onScroll, tho it doesn’t seem to work.

        if (firstVisibleItem == 0) {
            swipeLayout.setEnabled(true);
        } else {
            swipeLayout.setEnabled(false);
        }

EDIT2: THIS IS THE HEART OF THE ISSUE: It seems the onScroll method fires when the Activity first starts and the list loads and then never more again.

How to&Answers:

I had the same issue with RecyclerView and ListView. Scrolling downwards for whatever amount of items, it was impossible to return to the top of the list.

This will disable the SwipeRefreshLayout until the first visible item or any item position is visible. You can also bind different scroll listeners along this one. Make sure you enable (if previously disabled) SwipeRefreshLayout whenever you repopulate the listivew.

public class SwipeRefreshLayoutToggleScrollListenerListView implements AbsListView.OnScrollListener {
    private List<AbsListView.OnScrollListener> mScrollListeners = new ArrayList<AbsListView.OnScrollListener>();
    private int mExpectedVisiblePosition = 0;

    public SwipeRefreshLayoutToggleScrollListenerListView(SwipeRefreshLayout mSwipeLayout) {
        this.mSwipeLayout = mSwipeLayout;
    }

    private SwipeRefreshLayout mSwipeLayout;
    public void addScrollListener(AbsListView.OnScrollListener listener){
        mScrollListeners.add(listener);
    }
    public boolean removeScrollListener(AbsListView.OnScrollListener listener){
        return mScrollListeners.remove(listener);
    }
    public void setExpectedFirstVisiblePosition(int position){
        mExpectedVisiblePosition = position;
    }

    private void notifyOnScrolled(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){
        for(AbsListView.OnScrollListener listener : mScrollListeners){
            listener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
        }
    }
    private void notifyScrollStateChanged(AbsListView view, int scrollState){
        for(AbsListView.OnScrollListener listener : mScrollListeners){
            listener.onScrollStateChanged(view, scrollState);
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
      notifyScrollStateChanged(view, scrollState);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        notifyOnScrolled(view, firstVisibleItem, visibleItemCount, totalItemCount);
        if(firstVisibleItem != RecyclerView.NO_POSITION)
            mSwipeLayout.setEnabled(firstVisibleItem == mExpectedVisiblePosition);
    }
}

Edit:

lv.setOnScrollListener(new SwipeRefreshLayoutToggleScrollListenerListView(mSwiperLayout){
   //override methods here, don't forget the super calls. 
});

Answer:

You should override canChildScrollUp of SwipeRefreshView. This method is polled for the purpose of knowing whether the contained View wants to scroll up:

An extension with a settable interface for any arbritrary contained view:

public class SwipeRefreshWrapper extends SwipeRefreshLayout {
    private ScrollResolver mScrollResolver;

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

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

    public void setScrollResolver(ScrollResolver scrollResolver) {
        mScrollResolver = scrollResolver;
    }

    @Override
    public boolean canChildScrollUp() {
        if(mScrollResolver != null){
            return mScrollResolver.canScrollUp();
        }else {
            return super.canChildScrollUp();
        }
    }

    public static interface ScrollResolver{
        public boolean canScrollUp();
    }
}

Usage (ListView also has a nice method: canScrollVertically()):

final SwipeRefreshWrapper wrapper = (SwipeRefreshWrapper) rootView.findViewById(R.id.wrapper);
final ListView list = (ListView) rootView.findViewById(R.id.list);

wrapper.setScrollResolver(new SwipeRefreshWrapper.ScrollResolver() {
                              @Override
                              public boolean canScrollUp() {
                                 return list.canScrollVertically(-1);
                              }
                          });

Answer:

yourListview.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(timelogListView != null && timelogListView.getChildCount() > 0){
                boolean firstItemVisible = timelogListView.getFirstVisiblePosition() == 0;
                boolean topOfFirstItemVisible = timelogListView.getChildAt(0).getTop() == 0;
                enable = firstItemVisible && topOfFirstItemVisible;
            }
            swipeLayout.setEnabled(enable); 
            if(firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0)
            {
                if(flag_loading == false)
                {
                    flag_loading = true;
                    ConnectionDetector conn = new ConnectionDetector(getActivity());
                    if(conn.isConnectingToInternet()){
                        // call for your pagination async
                    }else{

                    }
                }
            }
        }
    });

By default : private boolean flag_loading = false; and in your pagination async if(YourListview.size() < 20) { flag_loading = true; } else{ flag_loading = false; }