umuieme
umuieme

Reputation: 859

In nested recyclerview, child recyclerview's GridLayoutManager.getChildCount() gives total item count

I am using a RecyclerView inside SwipeRefreshLayout.The RecyclerView has another 2 RecyclerView (for now; it may increase). In my second RecyclerView i am trying to implement infinite scrolling. But my RecyclerView.getItemCount() and RecyclerView.getChildCount() are giving same value. Also the 2nd re has GridLayoutManager and GridlayoutManager.findFirstVisibleItemPosition() always gives 0 and GridLayoutManager.findLastVisibleItemPosition() always gives list size - 1 in OnScrolled of the RecyclerView. What is causing this and what should i do to implement the infinite scrolling.

fragment.xml

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

<android.support.v7.widget.RecyclerView
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:paddingTop="@dimen/padding_standard"
    android:paddingBottom="@dimen/padding_standard">

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

parent_recyclerview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:layout_marginBottom="@dimen/padding_standard"
android:orientation="vertical">

<TextView
    android:id="@+id/section_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="@dimen/padding_standard"
    android:layout_marginBottom="@dimen/margin_standard"
    android:textColor="@color/label_text"
    android:textSize="@dimen/text_size_standard"
    android:textStyle="bold"
    tools:text="MOments"/>

<android.support.v7.widget.RecyclerView
    android:id="@+id/section_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clipToPadding="false"/>

<ProgressBar
    android:id="@+id/events_progress"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:visibility="gone"/>
</LinearLayout>

onScrollListener for child recycler view

  RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            GridLayoutManager manager = (GridLayoutManager) recyclerView.getLayoutManager();
            int itemSize = manager.getItemCount();
            int firstVisibleItem = manager.findFirstVisibleItemPosition();
            int visibleChIldCount = manager.getChildCount();
            Logger.e(TAG,"=============== START =====================");
            Logger.e(TAG, "itemSize: " + itemSize);
            Logger.e(TAG, "firstVisibleitem: " + firstVisibleItem);
            Logger.e(TAG, "visibleChIldCount: " + visibleChIldCount);
            Logger.e(TAG,"mLayoutManager.firstCOmpletely: "+ manager.findFirstCompletelyVisibleItemPosition());
            Logger.e(TAG,"mLayoutManager. lastcompletey: "+ manager.findLastCompletelyVisibleItemPosition());
                Logger.e(TAG,"mLayoutManager.findLastVisible: "+ manager.findLastVisibleItemPosition());
            Logger.e(TAG,"=================END ================");
            if (itemSize >= firstVisibleItem + visibleChIldCount){
                Logger.e("", "loading");
                    mLoadMoreListener.loadMore();

            } else {
                Logger.e(TAG, "not Loading");
            }
        }
};

Upvotes: 2

Views: 1880

Answers (1)

umuieme
umuieme

Reputation: 859

Sorry for the late reply. But i will post my solution here if in case someone else is looking for them.

In the adapter of the parent recycler view i have set tag for the view

@Override
public SectionRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = mLayoutInflater.inflate(R.layout.view_section, parent, false);
    view.setTag(viewType);
    return new SectionRowHolder(view);
}

The SectionRowHolder is simple ViewHolder with a RecyclerView.OnScrollListener property with getter and setter.

public class SectionRowHolder extends RecyclerView.ViewHolder {

    protected RecyclerView recyclerView;
    RecyclerView.OnScrollListener mOnScrollListener;

    public SectionRowHolder(View view) {
        super(view);
        this.recyclerView = (RecyclerView) view.findViewById(R.id.section_list);

    }

    public RecyclerView.OnScrollListener getCustomScrollListener() {
        return mOnScrollListener;
    }

    public void setCustomScrollListener(RecyclerView.OnScrollListener mOnScrollListener) {
        this.mOnScrollListener = mOnScrollListener;
    }
}

Then in the onBindViewHolder for the child with infinite scrolling I have implemented the load more logic in scroll listener and set to the child RecyclerView.

 RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {

        boolean loadEnable = false;

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            mTotalScrolled += dy;
            if ((mTotalScrolled + LOAD_MORE_ENABLE_HEIGHT) > recyclerView.getHeight() && loadEnable) {
                loadEnable = false;
                mLoadMoreListener.loadMore();
            } else {
                loadEnable = true;
            }
        }
    };
    holder.setCustomScrollListener(scrollListener);
    holder.recyclerView.addOnScrollListener(scrollListener);

Here LOAD_MORE_ENABLE_HEIGHT is offset from bottom of the child recycler view to initialize the loadmore() logic and mLoadMoreListener is callback to the fragment or activity.

Finally for passing the scoll listener from parent recycler view to the child recycler vew, in my parent RecyclerView's onScrollListener

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            View v = mRecyclerView.findViewWithTag(CHILD_RECYCLERVIEW_TAG);
            SectionedLifeAtAdapter.SectionRowHolder viewHolder =
                    (SectionedLifeAtAdapter.SectionRowHolder) mRecyclerView
                            .findContainingViewHolder(v);
            if (viewHolder.getCustomScrollListener() != null)
                viewHolder.getCustomScrollListener().onScrolled((RecyclerView) v
                        .findViewById(R.id.section_list), dx, dy);

            Logger.e(TAG, ">>> call to on scrolled listener >>>");
        }
    });

Here CHILD_RECYCLERVIEW_TAG is the view type that you set in the onCreateViewHolder of the parent Adapter. It kind of look like messy but it did the job for me without any issues.

Upvotes: 1

Related Questions