Friday, January 6, 2017

Android Populating Different View/Layout On RecyclerView's Item

Sometime on your recyclerview's item, you need to place different view/layout on each item. For example on item index 0 you need to place a form login and on item index 1 you need to place a form register, etc.


Okay, that's the imagine of how to place a different layout on recyclerview's item. Now we start the coding.

PREPARATION

Compile the following library on your build.gradle (app:module)

compile 'com.android.support:recyclerview-v7:25.0.0'

IMPLEMENTATION

This project place 3 different item on recyclerview's item. So first we create all the layout before start java code

1. activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
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="com.androidbie.differenctviewonrecyclerviewitem.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</RelativeLayout>
2. view_input_usernamepassword.xml 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/ll_input_username_password"
android:layout_width="match_parent"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="15dp"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textview_description_input_usernamepassword"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textview_name_input_usernamepassword"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textview_city_input_usernamepassword"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/edit_text_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Input username"/>
<EditText
android:id="@+id/edit_text_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Input Password"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_weight="1"
android:id="@+id/button_add_to_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add To List"/>
<Button
android:layout_weight="1"
android:id="@+id/button_done"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Done"/>
</LinearLayout>
</LinearLayout>
<View
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:background="@android:color/holo_blue_bright"
android:layout_height="2dp"/>
</LinearLayout>
3. view_please_wait.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/ll_progressbar"
android:layout_width="match_parent"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="15dp"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textview_description_please_wait"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textview_name_please_wait"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textview_city_please_wait"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<ProgressBar
android:layout_marginTop="10dp"
android:id="@+id/progressbar_display_account"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:layout_marginBottom="10dp"
android:text="Your TextView Loading"/>
</LinearLayout>
<View
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:background="@android:color/holo_blue_bright"
android:layout_height="2dp"/>
</LinearLayout>
4. view_detail_usernamepassword.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:id="@+id/ll_detail_view"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="15dp"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textview_description_detail"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textview_name_detail"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textview_city_detail"
android:layout_width="match_parent"
android:textColor="@android:color/black"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_weight="1"
android:id="@+id/textview_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Your Textview Detail 1"/>
<TextView
android:layout_weight="1"
android:gravity="center"
android:id="@+id/textview_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Your Textview Detail 2"/>
</LinearLayout>
</LinearLayout>
<View
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:background="@android:color/holo_blue_bright"
android:layout_height="2dp"/>
</LinearLayout>
After the layouts are finish, now we create all the java class that we used on this project. Start from :
 
1. ItemModel.java

In order program know that item index 0 for Layout A, item index 1 for Layout B and etc, you have to give an indicator in your Object/Mode/Data before transfer to your adapter.

In this project I put an index inside my model class as an indicator. The model namely as ItemModel.java. Paste the following code :

package com.androidbie.differenctviewonrecyclerviewitem.models;
/**
* Created by putuguna on 05/01/17.
*/
public class ItemModel {
private int index;
private String description;
private String name;
private String city;
public ItemModel(int index, String description, String name, String city) {
this.index = index;
this.description = description;
this.name = name;
this.city = city;
}
public ItemModel() {
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
view raw ItemModel.java hosted with ❤ by GitHub
2. ViewAdapter.java

Like i explained above (on the first paragraph), you have to create you inner class in ViewHolder (Whatever how much it is). If you wanna put 4 different layout, so create 4 different inner class of ViewHolder.

After that, you should to extends RecyclerView.Adapter<RecyclerView.ViewHolder> and then implement all of its methods.

Which method that explain that index 1 for layout A and etc?


For that, you have to override method getItemViewType(int position) manually. Create the condition using if and else. On this method you will use the indicator of your model as the key.

@Override
public int getItemViewType(int position) {
    ItemModel item = mListItemModel.get(position);
    if(item.getIndex()==0){
        return 0;
    }else if(item.getIndex()==1){
        return 1;
    }else if(item.getIndex()==2){
        return 2;
    }
    return super.getItemViewType(position);
}

These index or number got from model that we input on MainActivity (explained later).

After you create the condition, in onCreateViewHolder(ViewGroup parent, int viewType) you have to create the condition using case (or anything that related!). The logic is, if method getItemViewType() return index x, than put Layout x. Take a look at the code follows :

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder holder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType){
case 0:
View viewInputUserPassword = inflater.inflate(R.layout.view_input_username_and_password, parent, false);
holder = new InputUsernameAndPasswordViewHolder(viewInputUserPassword);
break;
case 1:
View viewLoading = inflater.inflate(R.layout.view_please_wait, parent, false);
holder = new LoadingPleaseWaitViewHolder(viewLoading);
break;
case 2:
View viewDetail = inflater.inflate(R.layout.view_detail_usernamepassword, parent, false);
holder = new DetailListPasswordAndUsernameViewHolder(viewDetail);
break;
}
return holder;
}
To get that the layout x has been return on method onCreateViewHolder(ViewGroup parent, int viewType), you must use an instanceof on method onBindViewHolder(RecyclerView.ViewHolder holder, final int position) . Take a look at the following sample code :

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if(holder instanceof InputUsernameAndPasswordViewHolder){
//DO activity of LoadingPleaseWaitViewHolder
}else if(holder instanceof LoadingPleaseWaitViewHolder){
//DO activity of LoadingPleaseWaitViewHolder
}else if(holder instanceof DetailListPasswordAndUsernameViewHolder){
//DO activity of DetailListPasswordAndUsernameViewHolder
}
}
I hope you'll understand how to steps to create a complex adapter like above. Here is the full code of ViewAdapter.java :

package com.androidbie.differenctviewonrecyclerviewitem;
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.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.androidbie.differenctviewonrecyclerviewitem.models.ItemModel;
import java.util.List;
/**
* Created by putuguna on 05/01/17.
*/
public class ViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private List<ItemModel> mListItemModel;
private Context mContext;
public ViewAdapter(List<ItemModel> mListItemModel, Context mContext) {
this.mListItemModel = mListItemModel;
this.mContext = mContext;
}
// override this method manually
@Override
public int getItemViewType(int position) {
ItemModel item = mListItemModel.get(position);
if(item.getIndex()==0){
return 0;
}else if(item.getIndex()==1){
return 1;
}else if(item.getIndex()==2){
return 2;
}
return super.getItemViewType(position);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder holder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType){
case 0:
View viewInputUserPassword = inflater.inflate(R.layout.view_input_username_and_password, parent, false);
holder = new InputUsernameAndPasswordViewHolder(viewInputUserPassword);
break;
case 1:
View viewLoading = inflater.inflate(R.layout.view_please_wait, parent, false);
holder = new LoadingPleaseWaitViewHolder(viewLoading);
break;
case 2:
View viewDetail = inflater.inflate(R.layout.view_detail_usernamepassword, parent, false);
holder = new DetailListPasswordAndUsernameViewHolder(viewDetail);
break;
}
return holder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
ItemModel itemModel = mListItemModel.get(position);
if(holder instanceof InputUsernameAndPasswordViewHolder){
((InputUsernameAndPasswordViewHolder) holder).tvDesc.setText("Description = "+itemModel.getDescription());
((InputUsernameAndPasswordViewHolder) holder).tvName.setText("Name = "+itemModel.getName());
((InputUsernameAndPasswordViewHolder) holder).tvCity.setText("City = " + itemModel.getCity());
// do onClick on LinearLayout to see the position of recyclerview item
((InputUsernameAndPasswordViewHolder) holder).llInputUsernamePassword.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(mContext, "RecyclerView's item position = " + position, Toast.LENGTH_SHORT).show();
}
});
}else if(holder instanceof LoadingPleaseWaitViewHolder){
((LoadingPleaseWaitViewHolder) holder).tvDesc.setText("Description = "+itemModel.getDescription());
((LoadingPleaseWaitViewHolder) holder).tvName.setText("Name = "+itemModel.getName());
((LoadingPleaseWaitViewHolder) holder).tvCity.setText(itemModel.getCity());
// do onClick on LinearLayout to see the position of recyclerview item
((LoadingPleaseWaitViewHolder) holder).llLoading.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(mContext, "RecyclerView's item position = " + position, Toast.LENGTH_SHORT).show();
}
});
}else if(holder instanceof DetailListPasswordAndUsernameViewHolder){
((DetailListPasswordAndUsernameViewHolder) holder).tvDesc.setText("Description = "+itemModel.getDescription());
((DetailListPasswordAndUsernameViewHolder) holder).tvName.setText("Name = "+itemModel.getName());
((DetailListPasswordAndUsernameViewHolder) holder).tvCity.setText("City = " + itemModel.getCity());
// do onClick on LinearLayout to see the position of recyclerview item
((DetailListPasswordAndUsernameViewHolder) holder).llDetail.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(mContext, "RecyclerView's item position = " + position, Toast.LENGTH_SHORT).show();
}
});
}
}
@Override
public int getItemCount() {
return mListItemModel.size();
}
/**
* first, create Input ViewHolder of username and password
*/
public class InputUsernameAndPasswordViewHolder extends RecyclerView.ViewHolder{
public EditText etUsername;
public EditText etPassword;
public Button btnAddToList;
public Button btnDone;
public TextView tvDesc;
public TextView tvName;
public TextView tvCity;
public LinearLayout llInputUsernamePassword;
public InputUsernameAndPasswordViewHolder(View itemView) {
super(itemView);
etPassword = (EditText) itemView.findViewById(R.id.edit_text_password);
etUsername = (EditText) itemView.findViewById(R.id.edit_text_username);
btnAddToList = (Button) itemView.findViewById(R.id.button_add_to_list);
btnDone = (Button) itemView.findViewById(R.id.button_done);
tvDesc = (TextView) itemView.findViewById(R.id.textview_description_input_usernamepassword);
tvName = (TextView) itemView.findViewById(R.id.textview_name_input_usernamepassword);
tvCity = (TextView) itemView.findViewById(R.id.textview_city_input_usernamepassword);
llInputUsernamePassword = (LinearLayout) itemView.findViewById(R.id.ll_input_username_password);
}
}
/**
* Second, create loading view holder to display loading view after finish input data
*/
public class LoadingPleaseWaitViewHolder extends RecyclerView.ViewHolder{
public LinearLayout llLoading;
public TextView tvDesc;
public TextView tvName;
public TextView tvCity;
public LoadingPleaseWaitViewHolder(View itemView) {
super(itemView);
llLoading = (LinearLayout) itemView.findViewById(R.id.ll_progressbar);
tvDesc = (TextView) itemView.findViewById(R.id.textview_description_please_wait);
tvName = (TextView) itemView.findViewById(R.id.textview_name_please_wait);
tvCity = (TextView) itemView.findViewById(R.id.textview_city_please_wait);
}
}
/**
* Third, create List ViewHolder to display list of username and password
*/
public class DetailListPasswordAndUsernameViewHolder extends RecyclerView.ViewHolder{
public TextView tvUsername;
public TextView tvPassword;
public TextView tvDesc;
public TextView tvName;
public TextView tvCity;
public LinearLayout llDetail;
public DetailListPasswordAndUsernameViewHolder(View itemView) {
super(itemView);
tvUsername = (TextView) itemView.findViewById(R.id.textview_username);
tvPassword = (TextView) itemView.findViewById(R.id.textview_password);
tvDesc = (TextView) itemView.findViewById(R.id.textview_description_detail);
tvName = (TextView) itemView.findViewById(R.id.textview_name_detail);
tvCity = (TextView) itemView.findViewById(R.id.textview_city_detail);
llDetail = (LinearLayout) itemView.findViewById(R.id.ll_detail_view);
}
}
}
3. MainActivity.java

In this class, as usual, just to set the data, define the recyclerview and set the adapter's data to recyclerview. Here the full code of MainActivity.java :

package com.androidbie.differenctviewonrecyclerviewitem;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import com.androidbie.differenctviewonrecyclerviewitem.models.ItemModel;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private List<ItemModel> mlistItemModel;
private RecyclerView recyclerView;
private ViewAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
mlistItemModel = new ArrayList<>();
mlistItemModel.add(new ItemModel(0,"This Form Login","Android Newbie","Bandung"));
mlistItemModel.add(new ItemModel(1,"This Form Loading","Android Expert","Canberra"));
mlistItemModel.add(new ItemModel(2,"This Form Detail","Android Middle","Kuala Lumpur"));
mlistItemModel.add(new ItemModel(0,"This Form Login","Android Newbie","Bandung"));
mlistItemModel.add(new ItemModel(2,"This Form Detail","Android Expert","London"));
mlistItemModel.add(new ItemModel(1,"This Form Loading","Android Middle","Barcelona"));
mAdapter = new ViewAdapter(mlistItemModel, this);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
}
}
That's all. Compile and run the project. Hope it works well. Thank you.

Related Posts


EmoticonEmoticon

:)
:(
hihi
:-)
:D
=D
:-d
;(
;-(
@-)
:o
:>)
(o)
:p
:-?
(p)
:-s
8-)
:-t
:-b
b-(
(y)
x-)
(h)