Android - OnScrollListener for Staggered Grid View

2019-01-25 00:33发布

问题:

Please excuse my English, I'm French...

So, I've got a question for my Android App. I've to integrate a grid view as Pinterest style. I found this lib : Staggered Grid View (https://github.com/maurycyw/StaggeredGridView)

It's work fine but... There is no OnScrollListener ! I had to know when the user see the last item, in order to load more. But it's not possible without OnScrollListener !

Have you got an idea for my problem ?

Thanks a lot.

回答1:

UPDATE:
After testing,
Calling notifyDataSetChanged() for StaggeredGridView Adapter case to reset the scroll position to 0 (Start of the Views).
Instead use PinterestLikeAdapterView


I have add loadMoreListener to the StaggeredGridView
steps:
1- add a loadmore Interface and booelan isLoading (at the top of the class)

public interface OnLoadMoreListener {
    public boolean onLoadMore();
}

private boolean mIsLoading;
private OnLoadMoreListener mLoadMoreListener;

2- find trackMotionScroll function, in the else of deltaY > 0
and after the up = false; add

if (overhang <= 80) { // 80 is how nearest to the end. ZERO mean the end of list
    // scrolling down and almost reach the end of list
    if (false == mIsLoading && null != mLoadMoreListener) {
        if (false == mLoadMoreListener.onLoadMore()) {
            mIsLoading = true;
            Log.d(TAG, "loadMore");
        }
    }
}

3- add setListener() and loadComplated() functions

public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
    this.mLoadMoreListener = onLoadMoreListener;
}

public void loadMoreCompleated() {
    mIsLoading = false;
}

HOW to use:
1- define a loadMoreListener in your Activity/Fragment

private StaggeredGridView.OnLoadMoreListener loadMoreListener = new StaggeredGridView.OnLoadMoreListener() {

    @Override
    public boolean onLoadMore() {
        loading.setVisibility(View.VISIBLE);
        // load more data from internet (not in the UI thread)

        return true; // true if you have more data to load, false you dont have more data to load 
    }
};

2- when you done data loading and add it to the adapter call

private void doneLoading() {
    gridView.loadMoreCompleated();
    loading.setVisibility(View.GONE);
}


回答2:

Try this if nothing works for you then wrap your recycler view in a scroll view and then check if scroll view has reached its bottom:

In your xml file:

<ScrollView
    android:id="@+id/scroll_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scrollbars="vertical"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

    </RelativeLayout>

</ScrollView>

In your class file:

private ScrollView mScrollView;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    initScrollView();
    ...
}

private void initScrollView() {
    mScrollView = (ScrollView) mView.findViewById(R.id.scroll_view);
    mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            if (mScrollView != null) {
                if (mScrollView.getChildAt(0).getBottom() <= (mScrollView.getHeight() + mScrollView.getScrollY())) {
                    // Scroll view is at bottom
                    // If not loading then start load more
                } else {
                    // Scroll view is not at bottom
                }
            }
        }
    });
}

Remember to set nested scrolling of recycler view to false for smooth scrolling in your class file:

mRecyclerView.setNestedScrollingEnabled(false);

If you want to start loading next page just before it reaches the bottomm, then just subtract an integer from mScrollView.getChildAt(0).getBottom()

For example 1000 is subtracted here:

if (mScrollView.getChildAt(0).getBottom() - 1000 <= (mScrollView.getHeight() + mScrollView.getScrollY())) {
    // Scroll view is at bottom
    // If not loading then start load more
} else {
    // Scroll view is not at bottom
}

Use a greater integer to start loading much before the scroll reaches bottom.



回答3:

had to know when the user see the last item, in order to load more. But it's not possible without OnScrollListener !

Why would you use onScrollListener for that? Instead, write a class (MyStaggeredGridAdapter, perhaps?) that extends BaseAdapter and apply it to the StaggeredGridView. Then you can use the adapter's getView() method, which will be called whenever a new view needs to be rendered.



回答4:

To know when the last item is shown on the screen, i use the Adapter's getView() method. Just compare your last index with the "position" parameter. Something like this

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ...

        if (lastLoaded == position){
            loadMore();
        }

        ...
    }

and maybe then you would like to see this: How to add data into bottom of Android StaggeredGridView and not go back top? to avoid load the list from the begining and continue from the last item shown.

i hope this helps, don't know if it's the best solution, but is working for me ;)