In this tutorial I am explaining how to implement multiple layout in a single RecyclerView
Add ‘com.android.support:recyclerview‘ in Gradle dependencies and sync it (Check this tutorial for Recycler View example https://wiki.workassis.com/android-recyclerview-example/)
MainActivity
package samples.bm.com.myapplication; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.widget.Toast; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; public class MainActivity extends AppCompatActivity implements MyMediatorInterface { private MyAdapter mAdapter; private ArrayList<ItemInterface> mUsersAndSectionList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); ArrayList<UserModel> usersList = new ArrayList<>(); try { usersList.add(new UserModel("Jos", "123546567", sdf.parse("2016-1-1"))); usersList.add(new UserModel("Kiran", "456546456", sdf.parse("2016-1-1"))); usersList.add(new UserModel("Manu", "5678", sdf.parse("2016-3-31"))); usersList.add(new UserModel("Roy", "67443453", sdf.parse("2016-1-31"))); usersList.add(new UserModel("Musthu", "456353", sdf.parse("2016-1-31"))); usersList.add(new UserModel("Jaffer", "4644", sdf.parse("2016-1-31"))); } catch (ParseException e) { e.printStackTrace(); } mUsersAndSectionList = new ArrayList<>(); getSectionalList(usersList); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv_my_recycler_view); recyclerView.setHasFixedSize(true); final GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2); gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (MyAdapter.SECTION_VIEW == mAdapter.getItemViewType(position)) { return 2; } return 1; } }); recyclerView.setLayoutManager(gridLayoutManager); mAdapter = new MyAdapter(mUsersAndSectionList, this); recyclerView.setAdapter(mAdapter); } private void getSectionalList(ArrayList<UserModel> usersList) { Collections.sort(usersList, new Comparator<UserModel>() { @Override public int compare(UserModel user1, UserModel user2) { return user1.jDate.compareTo(user2.jDate) > 0 ? 1 : 0; } }); String lastHeader = ""; int size = usersList.size(); for (int i = 0; i < size; i++) { UserModel user = usersList.get(i); String header = getSimpleDate(user.jDate); if (!TextUtils.equals(lastHeader, header)) { lastHeader = header; mUsersAndSectionList.add(new GroupTitleModel(header)); } mUsersAndSectionList.add(user); } } public static String getSimpleDate(Date date) { SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy"); String stringdate = format.format(date); return stringdate; } @Override public void userItemClick(int pos) { Toast.makeText(MainActivity.this, "Clicked User : " + ((UserModel) mUsersAndSectionList.get(pos)).name, Toast.LENGTH_SHORT).show(); } }
MyMediatorInterface
package samples.bm.com.myapplication; public interface MyMediatorInterface { void userItemClick(int pos); }
MyAdapter
package samples.bm.com.myapplication; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import java.lang.ref.WeakReference; import java.util.ArrayList; public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public static final int SECTION_VIEW = 0; public static final int CONTENT_VIEW = 1; ArrayList<ItemInterface> mUsersAndSectionList; WeakReference<Context> mContextWeakReference; public MyAdapter(ArrayList<ItemInterface> usersAndSectionList, Context context) { this.mUsersAndSectionList = usersAndSectionList; this.mContextWeakReference = new WeakReference<Context>(context); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Context context = mContextWeakReference.get(); if (viewType == SECTION_VIEW) { return new SectionViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item_group_title, parent, false)); } return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.row_user_item, parent, false), context); } @Override public int getItemViewType(int position) { if (mUsersAndSectionList.get(position).isSection()) { return SECTION_VIEW; } else { return CONTENT_VIEW; } } @Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { Context context = mContextWeakReference.get(); if (context == null) { return; } if (SECTION_VIEW == getItemViewType(position)) { SectionViewHolder sectionViewHolder = (SectionViewHolder) holder; GroupTitleModel sectionItem = ((GroupTitleModel) mUsersAndSectionList.get(position)); sectionViewHolder.title.setText(sectionItem.title); return; } MyViewHolder myViewHolder = (MyViewHolder) holder; UserModel currentUser = ((UserModel) mUsersAndSectionList.get(position)); myViewHolder.TvName.setText(currentUser.name); myViewHolder.TvPhone.setText(currentUser.phone); } @Override public int getItemCount() { return mUsersAndSectionList.size(); } //holder public static class MyViewHolder extends RecyclerView.ViewHolder { public TextView TvName, TvPhone; public LinearLayout ll; public MyViewHolder(View itemView, final Context context) { super(itemView); TvName = (TextView) itemView.findViewById(R.id.tv_name); TvPhone = (TextView) itemView.findViewById(R.id.tv_phone); ll = (LinearLayout) itemView.findViewById(R.id.ll_layout); ll.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ((MainActivity) context).userItemClick(getAdapterPosition()); } }); } } public class SectionViewHolder extends RecyclerView.ViewHolder { TextView title; public SectionViewHolder(View itemView) { super(itemView); title = (TextView) itemView.findViewById(R.id.tv_group_title); } } }
GroupTitleModel
package samples.bm.com.myapplication; public class GroupTitleModel implements ItemInterface { public String title; public GroupTitleModel(String title) { this.title = title; } @Override public boolean isSection() { return true; } }
UserModel
package samples.bm.com.myapplication; import java.util.Date; public class UserModel implements ItemInterface{ public String name; public String phone; public Date jDate; public UserModel(String name, String phone, Date jDate) { this.name = name; this.phone = phone; this.jDate = jDate; } @Override public boolean isSection() { return false; } }
ItemInterface
package samples.bm.com.myapplication; public interface ItemInterface { boolean isSection(); }
Layouts
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="samples.bm.com.myapplication.MainActivity" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv_my_recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false"/> </LinearLayout>
row_item_group_title.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#f9aaaa" android:padding="5dp"> <TextView android:id="@+id/tv_group_title" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
row_user_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <ImageView android:layout_gravity="center" android:layout_width="100dp" android:layout_height="100dp" android:src="@mipmap/ic_launcher"/> <TextView android:id="@+id/tv_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAlignment="center" android:text="name"/> <TextView android:id="@+id/tv_phone" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAlignment="center" android:text="23423424242"/> </LinearLayout>
Output
(For using multiple layout in RecyclerView check this tutorial )
Add ‘com.android.support:recyclerview‘ in Gradle dependencies and sync it
my app/build.gradle file
apply plugin: 'com.android.application' android { compileSdkVersion 24 buildToolsVersion "24.0.1" defaultConfig { applicationId "samples.bm.com.myapplication" minSdkVersion 14 targetSdkVersion 24 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.2.0' compile 'com.android.support:recyclerview-v7:24.2.0' }
MainActivity
package samples.bm.com.myapplication; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.Toast; import java.util.ArrayList; public class MainActivity extends AppCompatActivity implements MyMediatorInterface { private MyAdapter mAdapter; private ArrayList<UserModel> usersList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); usersList = new ArrayList<>(); usersList.add(new UserModel("Jos", "123546567")); usersList.add(new UserModel("Kiran", "456546456")); usersList.add(new UserModel("Manu", "5678")); usersList.add(new UserModel("Roy", "67443453")); usersList.add(new UserModel("Musthu", "456353")); usersList.add(new UserModel("Jaffer", "4644")); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv_my_recycler_view); recyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); mAdapter = new MyAdapter(usersList, this); recyclerView.setAdapter(mAdapter); } @Override public void userItemClick(int pos) { Toast.makeText(MainActivity.this, "Clicked User : " + usersList.get(pos).name, Toast.LENGTH_SHORT).show(); } }
Model
package samples.bm.com.myapplication; public class UserModel { public String name; public String phone; public UserModel(String name, String phone) { this.name = name; this.phone = phone; } }
Adapter
package samples.bm.com.myapplication; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import java.lang.ref.WeakReference; import java.util.ArrayList; public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { ArrayList<UserModel> mUsersList; WeakReference<Context> mContextWeakReference; public MyAdapter(ArrayList<UserModel> usersList, Context context) { mUsersList = usersList; this.mContextWeakReference = new WeakReference<Context>(context); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Context context = mContextWeakReference.get(); if (context != null) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_user_item, parent, false); return new MyViewHolder(itemView, context); } return null; } @Override public void onBindViewHolder(final MyViewHolder holder, int position) { Context context = mContextWeakReference.get(); if (context == null) { return; } UserModel currentUser = mUsersList.get(position); holder.TvName.setText(currentUser.name); holder.TvPhone.setText(currentUser.phone); } @Override public int getItemCount() { return mUsersList.size(); } //holder public static class MyViewHolder extends RecyclerView.ViewHolder { public TextView TvName, TvPhone; public LinearLayout ll; public MyViewHolder(View itemView, final Context context) { super(itemView); TvName = (TextView) itemView.findViewById(R.id.tv_name); TvPhone = (TextView) itemView.findViewById(R.id.tv_phone); ll = (LinearLayout) itemView.findViewById(R.id.ll_layout); ll.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ((MainActivity) context).userItemClick(getAdapterPosition()); } }); } } }
Interface:
package samples.bm.com.myapplication; public interface MyMediatorInterface { void userItemClick(int pos); }
Layouts
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="samples.bm.com.myapplication.MainActivity" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv_my_recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
Recycler View row
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/ll_layout" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20px"> <TextView android:id="@+id/tv_name" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv_phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="right" /> </LinearLayout>
Out Put
If you want to add data to RecyclerView add data into the Array List (eg:- usersList.add(new UserModel(“new name”, “345”)); and you can call the adapter function notifyItemInserted() or notifyDatasetChanged().
mAdapter.notifyItemInserted(position);
mAdapter.notifyDataSetChanged(); //this function you can call with any activity (inset,update,delete) but it is expensive
While editing edit the value in array list and call notifyItemChanged(position), while deleting delete the position from array list and call notifyItemRemoved(position)