Monday, March 13, 2017

Android - Load more and Empty view in RecycleView

If you already read my previous blog that is related to this. Almost same thing i'm going implement here except empty text view. it will visible if list has no items. I'm going to create a custom RecylceView for track load more event.


AppRecyclerView is a customized class of RecyclerView that track load more event on list scroll. 

1. Here is your screen layout file that contains custom recyclerView, progressBar and Textview that shows the empty message "Record not found".


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

        <com.demo.AppRecyclerView
            android:id="@+id/list_rv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="none"
            />

        <ProgressBar
            android:id="@+id/list_pb_loader"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_gravity="bottom|center"
            android:layout_marginBottom="10dp"
            android:background="@color/colorTransparent"
            android:indeterminateTint="@color/colorPrimaryDark"
            android:indeterminateTintMode="src_atop"
            android:visibility="gone"
            />

        <TextView
            android:id="@+id/list_tv_list_msg"
            style="@style/AppBigTextViewStyleLabel"
            android:layout_width="match_parent"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="Record not found"
            android:textColor="@color/colorLightGrey"
            android:visibility="gone"
            />
    </FrameLayout>



2.  In your Activity/Fragment setup the following views.


        ProgressBar progressBar = (ProgressBar) rootView.findViewById(R.id.fragment_product_list_pb_loader);
        progressBar.getIndeterminateDrawable().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorPrimaryDark), PorterDuff.Mode.SRC_IN);

        rvProductList = (AppRecyclerView) rootView.findViewById(R.id.fragment_product_list_rv);

       // Provide load more view that will visible when last item come on screen.
        rvProductList.setLoadMoreProgress(progressBar); 

       //Set listener that invoke when laod more event invoke from custom AppRecyclerView
        rvProductList.setLoadMoreListener(presenter);
           rvProductList.setEmptyView(rootView.findViewById(R.id.fragment_product_list_tv_list_msg));

3. Customize AppRecyclerView


public class AppRecyclerView extends RecyclerView {
    private ProgressBar progressBar;
    private View emptyView;
    private boolean loading;
    private OnLoadMoreListener onLoadMoreListener; 


   //It will observe item of list and show empty view if list not contains any item.
    private AdapterDataObserver emptyObserver = new AdapterDataObserver() {
        @Override
        public void onChanged() {
            Adapter<?> adapter = getAdapter();
            if (adapter != null && emptyView != null) {
                if (adapter.getItemCount() == 0) {
                    emptyView.setVisibility(View.VISIBLE);
                    AppRecyclerView.this.setVisibility(View.GONE);
                } else {
                    emptyView.setVisibility(View.GONE);
                    AppRecyclerView.this.setVisibility(View.VISIBLE);
                }
            }
        }
    };


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


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


    public AppRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setAdapter(Adapter adapter) {
        super.setAdapter(adapter);
        if (adapter != null && !adapter.hasObservers()) {
            adapter.registerAdapterDataObserver(emptyObserver);
        }

        emptyObserver.onChanged();
    }


    public void setEmptyView(View emptyView) {
        this.emptyView = emptyView;
    }

    @Override
    public void stopScroll()
    {
        try {
            super.stopScroll();
        } catch (NullPointerException exception) {
            Crashlytics.logException(exception);
            /**
             *  The mLayout has been disposed of before the
             *  RecyclerView and this stops the application
             *  from crashing.
             */
        }
    }


    public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {

        this.onLoadMoreListener = loadMoreListener;

        addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView,
                                   int dx, int dy)
            {
                super.onScrolled(recyclerView, dx, dy);
                if (getLayoutManager() instanceof LinearLayoutManager) {
                    validateListScroll(dy, (LinearLayoutManager) getLayoutManager());
                } else {
                    validateGridListScroll(dy, (GridLayoutManager) getLayoutManager());
                }
            }
        });
    }


    private void validateGridListScroll(int dy, GridLayoutManager gridLayoutManager) {
        if (dy > 0 && (gridLayoutManager.getChildCount() + gridLayoutManager.findFirstVisibleItemPosition() + 1) >= gridLayoutManager.getItemCount() && !loading) {
            setLoading(true);
            if (onLoadMoreListener != null) {
                onLoadMoreListener.onLoadMore();
            }
        }
    }


    private void validateListScroll(int dy, LinearLayoutManager linearLayoutManager) {
        if (dy > 0 && (linearLayoutManager.getChildCount() + linearLayoutManager.findFirstVisibleItemPosition() + 1) >= linearLayoutManager.getItemCount() && !loading) {
            setLoading(true);
            if (onLoadMoreListener != null) {
                onLoadMoreListener.onLoadMore();
            }
        }
    }

    public void setLoading(boolean loading) {
        this.loading = loading;
        if (progressBar != null) {
            if (loading) {
                progressBar.setVisibility(View.VISIBLE);
            } else {
                progressBar.setVisibility(View.GONE);
            }
        }
    }


    public void setLoadMoreProgress(ProgressBar progressBar) {
        this.progressBar = progressBar;
    }

    public interface OnLoadMoreListener {
    
        void onLoadMore();
    }
}
Share:

Get it on Google Play

React Native - Start Development with Typescript

React Native is a popular framework for building mobile apps for both Android and iOS. It allows developers to write JavaScript code that ca...