Skip to content Skip to sidebar Skip to footer

How To Use The Same Recyclerview Adapter For Different Layouts

I am developing an application which heavily relies on the usage of RecyclerView. I really need to know how to use the same RecyclerView for different item layouts. An example of l

Solution 1:

Since the recyclerview item in xml doesn't depend on the kind of items that you will inflating in it, you can go ahead and use the same recycler view layout file for the three fragments.

As for the adapters, your lists seem to be homogeneous (i.e., single kind of view item). Its best that you use 3 different adapters for each case. You can customise the constructor, add custom helper methods for each kind of adapter as per your convenience.

Now if you have a heterogeneous list, you will have to override getItemViewType() in your adapter and use this appropriately in onCreateViewHolder() and onBindViewHolder()

Hope this helps! :)

Solution 2:

I came across similar situation and here is the model i followed.

First of all, Fragment layout file.

fragment layout file is not going to change for all 3 fragments(basically it is similar to list fragment), so I created a template file for list fragment.

list_fragment_template.xml

<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><android.support.v7.widget.RecyclerViewandroid:id="@+id/list"android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout>

Now fragment code :

In my case all the 3 fragments do almost same stuff (get recycler view, get adapter, recycler view decoration and some more operations etc).

Created an AbstrctFragment which extends fragment and overrided onCreate onAttach onDestroy etc. Since only type of data recyclerview consumes and adapters to push data to recycelrview would change for each of the fragment, create an abstract function to getAdapter and templatize data. Each of the three fragments will be derived from this AbstractFragment.

publicabstractclassAbstractFragment<E> extendsFragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragmentViewview= inflater.inflate(R.layout.template_list_fragment, container, false);


            mRecyclerView = (RecyclerView) view.findViewById(R.id.list);

            // get adapter to show item list// and fetch data.
            mRecyclerAdapter = getAdapter();
            mRecyclerView.setAdapter(mRecyclerAdapter);

            // show it as vertical list
            mRecyclerView.setLayoutManager(newLinearLayoutManager(getActivity()));
            // add seperator between list items.
            mRecyclerView.addItemDecoration(newDividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));

return view;
    }

... onAttach onDetach and whatever common memberfunctions and member variables that comes for each fragment.

Now RecyclerView layout files. Since all of them are different in layout, obviously they must be different.

RecyclerViewAdapters : Again here common code would be to member declarations, CreateViewHolder (here only layout name changes rest all code is same) and any other function which all of these adapters would share. (something like filtering list items).

similar to how we did for fragments, you can keep this in AbstractRecyclerViewAdapter and make bindViewholder etc as abstract functions and have 3 different recyclerAdapters which would derive from this AbstractRecyclerViewAdapter..

Solution 3:

its too late but, might be helpful for someone needy developer Your adapter should look like this, also you can add header and footer using this sample

publicclassSampleAdapterextendsRecyclerView.Adapter<SampleAdapter.ViewHolder> {

// Declaring Variable to Understand which View is being worked on// IF the view under inflation and population is header or ItemprivatestaticfinalintTYPE_HEADER=0;
privatestaticfinalintTYPE_ITEM=1;
privatestaticfinalintTYPE_FOOTER=2;

private Activity mContext;
private ArrayList<DataModel> _mItems;
privateint mLayout;
private String mProductHeadingTitle="Heading";
private String mProductHeadingSubTitle="SubHeading";
private String loadingText="LOADING";
privateint visibility= View.VISIBLE;

publicinterfaceSampleAdapterInterface {
     voiditemClicked(int position);
}

SampleAdapterInterface mCallBack;

publicSampleAdapter(Activity context, ArrayList<DataModel> items, int item_layout) {
    if (_mItems != null) {
        _mItems.clear();
    }
    this.mContext = context;
    this._mItems = items;
    this.mLayout = item_layout;
    mCallBack = (SampleAdapterInterface) context;
}

@OverridepublicintgetItemCount() {
    return _mItems.size()+2; // +2 for header and footer
}

@OverridepublicintgetItemViewType(int position) {

    if (position==0)
        return TYPE_HEADER;
    elseif(position==(_mItems.size()+1))
        return TYPE_FOOTER;

    return TYPE_ITEM;
}

publicvoidsetHeaderData(String title,String subTitle)
{
    this.mProductHeadingTitle=title;
    this.mProductHeadingSubTitle=subTitle;

    Log.d("LOG", "ProductHeadingTitle: " + mProductHeadingTitle);
    Log.d("LOG", "ProductHeadingSubTitle: " + mProductHeadingSubTitle);

    notifyDataSetChanged();
}

publicvoidsetFooterData(String loadingText,int visibility)
{
    this.loadingText=loadingText;
    this.visibility=visibility;

    Log.d("LOG", "LoadingText: " + loadingText);
    Log.d("LOG", "Visibility: " + visibility);

    notifyDataSetChanged();
}

@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


    if (viewType == TYPE_HEADER)
    {
        Viewview= LayoutInflater.from(parent.getContext()).inflate(R.layout.header_layout,parent,false);

        ViewHoldervhHeader=newViewHolder(view,viewType);

        return vhHeader;
    }
    elseif (viewType == TYPE_ITEM)
    {
        Viewview= LayoutInflater.from(parent.getContext()).inflate(mLayout,parent,false);

        //Creating ViewHolder and passing the object of type viewViewHoldervhItem=newViewHolder(view,viewType);

        return vhItem;
    }
    elseif (viewType == TYPE_FOOTER)
    {
        Viewview= LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_lyout,parent,false);

        ViewHoldervhFooter=newViewHolder(view,viewType);

        return vhFooter;
    }
    returnnull;
}

@OverridepublicvoidonBindViewHolder(ViewHolder viewHolder, int pos) {


    if(viewHolder.Holderid ==0)
    {
        // header view
        Log.d("LOG", "in header binder");
        viewHolder.mProductCatalogTitle.setText(mProductHeadingTitle);
        viewHolder.mProductCatalogSubTitle.setText(mProductHeadingSubTitle);
    }
    elseif(viewHolder.Holderid==1)
    {
        finalint position=pos-1; // -1 to substract header number// your code
    }
    elseif(viewHolder.Holderid==2)
    {
        // footer
        Log.d("LOG", "in footer binder");
        viewHolder.mProgressBar.setVisibility(visibility);
        viewHolder.mLoading.setText(loadingText);
    }


}

classViewHolderextendsRecyclerView.ViewHolder {

    int Holderid;

    // header
    TextView mProductCatalogTitle;
    TextView mProductCatalogSubTitle;

    //list// item type variable declaration// footer
    ProgressBar mProgressBar;
    TextView mLoading;

    publicViewHolder(View itemView, int viewType) {
        super(itemView);
        // Here we set the appropriate view in accordance with the the view type as passed when the holder object is createdif(viewType == TYPE_HEADER)
        {
            Holderid = 0;
            mProductCatalogTitle = (TextView) itemView.findViewById(R.id.tv_title);
            mProductCatalogSubTitle = (TextView) itemView.findViewById(R.id.tv_subtitle);
        }
        elseif(viewType == TYPE_ITEM)
        {
            Holderid = 1;
            itemView.setClickable(true);
            itemView.setOnClickListener(newOnClickListener() {
                @OverridepublicvoidonClick(View v) {
                    mCallBack.itemClicked(getAdapterPosition()-1);
                }
            });
            // initialize the view holder
        }

        elseif(viewType == TYPE_FOOTER)
        {
            Holderid = 2;
            mLoading = (TextView) itemView.findViewById(R.id.tv_loading);
            mProgressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
        }
    }
}

in your activity

// Adding to adapter as gridview when grid button clickedprivatevoidsetProductGridAdapter() {
    mListViewTab.setVisibility(View.VISIBLE);
    mGridViewTab.setVisibility(View.INVISIBLE);

    mSampleAdapter = newSampleAdapter(YourActicity.this,
            yourlist,R.layout.item_product_grid);
    mRecyclerView.setAdapter(mSampleAdapter);

    mRecyclerView.setHasFixedSize(true);

    finalGridLayoutManagerlayoutManager=newGridLayoutManager(getActivity(),
            2,                              //number of columns
            LinearLayoutManager.VERTICAL,   // orientationfalse);                         //reverse layout
    mRecyclerView.setLayoutManager(layoutManager);

    layoutManager.setSpanSizeLookup(newGridLayoutManager.SpanSizeLookup() {
        @OverridepublicintgetSpanSize(int position) {

            // to show header and footer in full rowif(position==0 || position==(yourlist.size()+1))
                return layoutManager.getSpanCount();
            elsereturn1;
        }
    });

    mRecyclerView.scrollToPosition(AppController.currentPosition);

    mSampleAdapter.notifyDataSetChanged();

    // Scroll listener for RecyclerView to call load more products
    mRecyclerView.setOnScrollListener(newRecyclerView.OnScrollListener() {

        @OverridepublicvoidonScrolled(RecyclerView recyclerView, int dx, int dy) {

            intvisibleItemCount= layoutManager.getChildCount();
            inttotalItemCount= layoutManager.getItemCount();
            intfirstVisibleItem= layoutManager.findFirstVisibleItemPosition();

            intlastInScreen= firstVisibleItem + visibleItemCount;
            if ((lastInScreen >= totalItemCount) && !isLoading) {
                //last item// do something after last item like load more code or // show No more items string
                mSampleAdapter.setFooterData("NO More Items",View.INVISIBLE);
            }
            AppController.currentPosition = firstVisibleItem;
        }
    });

}

// Adding to adapter as listview when list button clickedprivatevoidsetProductListAdapter() {
    mListViewTab.setVisibility(View.INVISIBLE);
    mGridViewTab.setVisibility(View.VISIBLE);

    mSampleAdapter = newSampleAdapter(YourActicity.this, yourlist,R.layout.item_product_list);
    mRecyclerView.setAdapter(mSampleAdapter);

    mRecyclerView.setHasFixedSize(true);

    finalLinearLayoutManagerlayoutManager=newLinearLayoutManager(getActivity(),
            LinearLayoutManager.VERTICAL,   // orientationfalse);                         //reverse layout
    mRecyclerView.setLayoutManager(layoutManager);

    mRecyclerView.scrollToPosition(AppController.currentPosition);
    mSampleAdapter.notifyDataSetChanged();

    // Scroll listener for RecyclerView to call load more products
    mRecyclerView.setOnScrollListener(newRecyclerView.OnScrollListener() {

        @OverridepublicvoidonScrolled(RecyclerView recyclerView, int dx, int dy) {

            intvisibleItemCount= layoutManager.getChildCount();
            inttotalItemCount= layoutManager.getItemCount();
            intfirstVisibleItem= layoutManager.findFirstVisibleItemPosition();

            intlastInScreen= firstVisibleItem + visibleItemCount;
            if ((lastInScreen >= totalItemCount) && !isLoading) {
                //last item// do something after last item like load more code or // show No more items string
                mSampleAdapter.setFooterData("NO MOre Items",View.INVISIBLE);
            }
            AppController.currentPosition = firstVisibleItem;
        }
    });
}

and your activity must implement SampleAdapterInterface in activity to get callback from adapter. Call those methods when toggling button from grid to list and vice versa

Solution 4:

//To setViewType maybe is a solution for you.Sample below:  privatestaticfinalintTYPE_DESC=0;
privatestaticfinalintTYPE_IMAGE= TYPE_DESC + 1;
privatestaticfinalintTYPE_THREE_TEXT= TYPE_IMAGE + 1;
publicintgetItemViewType(int position) {
    inttype=super.getItemViewType(position);
    try
    {
        type = Integer.parseInt(data.get(position).get("type"));
    } catch (Exception e)
    {
        e.printStackTrace();
    }
    return type;
}

publicintgetViewTypeCount() {
    return3;
}
public View getView(int position, View convertView, ViewGroup parent) {
    inttype= TYPE_DESC;
    try
    {
        type = Integer.parseInt(data.get(position).get("type"));
    } catch (Exception e)
    {
        e.printStackTrace();
    }
    ViewHolderholder=null;
    if (convertView == null)
    {
        System.out.println("getView::convertView is null");
        holder = newViewHolder();
        switch (type)
        {
            case TYPE_DESC:
                convertView = View.inflate(getBaseContext(),
                        R.layout.listitem_1, null);
                break;
            case TYPE_IMAGE:
                convertView = View.inflate(getBaseContext(),
                        R.layout.listitem_2, null);
                break;
            case TYPE_THREE_TEXT:
                convertView = View.inflate(getBaseContext(),
                        R.layout.listitem_3, null);
                break;
        }
        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    }
    //TODOreturn convertView;
}

Post a Comment for "How To Use The Same Recyclerview Adapter For Different Layouts"