We using listview with reason that listview have a view called ExpandableListView, so we just set the data through ExapandableListView.
But in several case, your application required a Recyclerview (I don't know what it is) instead of Listview.
Indeed, create a expandable view using recyclerview is more difficult that using ExpandableListview. You have to create all materials or view not just set the data.
But don't worry, i have spent several hours just to create simple expandable view using recyclerview, with hope you will easy to understand the steps.
PREPARATION
Compile the following libraries :
compile 'com.android.support:design:23.2.0' compile 'com.android.support:cardview-v7:23.2.0' compile 'com.android.support:recyclerview-v7:23.2.0'
After that, download LIB MODULE EXPANDABLE , extract and then place in your main package. Confuse? Take a look at Figure 1 :
![]() |
Figure 1 |
Place the LIB MODULE EXPANDABLE look like figure 1.
IMPLEMENTATION
Create new 3 xml layouts :
- activity_main.xml
- item_list_parent.xml
- item_list_child.xml
At Figure 1, there are several packages that have some java classes.
Package models
- BiodataChildModel.java
- BiodataParentModel.java
Package expandables
- BiodataChildViewHolder.java
- BiodataParentViewHolder.java
- BiodataExpandable.java
And last, definitely MainActivity.java.
First, modify the layouts that we've prepared.
activity_main.xml. Paste the following code :
item_list_child.xml. Paste the following code :
item_list_parent.xml. Paste the following code :
Second, we modify the code of all the java classes inside the package models. Why this package is first? Because this classes will use in next next java classes.
activity_main.xml. Paste the following code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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: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" | |
android:orientation="vertical" | |
tools:context="com.androidbie.recyclerviewexapandable.MainActivity"> | |
<LinearLayout | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:orientation="horizontal"> | |
<TextView | |
android:layout_marginLeft="@dimen/value_20" | |
android:layout_weight="1" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:text="@string/lbl_people_name"/> | |
<TextView | |
android:layout_marginLeft="@dimen/value_20" | |
android:layout_weight="1" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:text="@string/lbl_people_age"/> | |
</LinearLayout> | |
<android.support.v7.widget.RecyclerView | |
android:id="@+id/recyclerview" | |
android:layout_marginTop="@dimen/value_20" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView> | |
</LinearLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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:padding="@dimen/value_20" | |
android:layout_height="wrap_content"> | |
<TextView | |
android:id="@+id/text_view_status" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="@string/lbl_status"/> | |
<TextView | |
android:id="@+id/text_view_desc" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="@string/lbl_description"/> | |
</LinearLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<android.support.v7.widget.CardView | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
xmlns:android="http://schemas.android.com/apk/res/android"> | |
<LinearLayout | |
android:id="@+id/ll_item" | |
android:paddingRight="@dimen/value_20" | |
android:paddingLeft="@dimen/value_20" | |
android:orientation="horizontal" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content"> | |
<TextView | |
android:layout_weight="1" | |
android:id="@+id/textview_name" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:gravity="center|left" | |
android:text="@string/lbl_name"/> | |
<TextView | |
android:layout_weight="1" | |
android:id="@+id/textview_age" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:gravity="center" | |
android:text="@string/lbl_age"/> | |
<ImageView | |
android:id="@+id/image_view_collapse" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:src="@drawable/ic_content_add"/> | |
</LinearLayout> | |
</android.support.v7.widget.CardView> |
1. Package MODELS
Open BiodataChildModel.java. This class store all the data that will show on expand view. Paste the following code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.androidbie.recyclerviewexapandable.models; | |
/** | |
* Created by putuguna on 04/01/17. | |
*/ | |
public class BiodataChildModel { | |
private String status; | |
private String descriptions; | |
public BiodataChildModel(String status, String descriptions) { | |
this.status = status; | |
this.descriptions = descriptions; | |
} | |
public BiodataChildModel() { | |
} | |
public String getStatus() { | |
return status; | |
} | |
public void setStatus(String status) { | |
this.status = status; | |
} | |
public String getDescriptions() { | |
return descriptions; | |
} | |
public void setDescriptions(String descriptions) { | |
this.descriptions = descriptions; | |
} | |
} |
Because this class as the parent, you have to extends ParentListItem. After you do extends, you have to implements its methods. Take a look at the following code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.androidbie.recyclerviewexapandable.models; | |
import com.androidbie.recyclerviewexapandable.libmoduleExpandable.Model.ParentListItem; | |
import java.util.List; | |
/** | |
* Created by putuguna on 04/01/17. | |
*/ | |
public class BiodataParentModel implements ParentListItem { | |
private String name; | |
private String age; | |
private List<BiodataChildModel> mListChild; | |
public BiodataParentModel(String name, String age, List<BiodataChildModel> mListChild) { | |
this.name = name; | |
this.age = age; | |
this.mListChild = mListChild; | |
} | |
public BiodataParentModel() { | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
public String getAge() { | |
return age; | |
} | |
public void setAge(String age) { | |
this.age = age; | |
} | |
public List<BiodataChildModel> getmListChild() { | |
return mListChild; | |
} | |
public void setmListChild(List<BiodataChildModel> mListChild) { | |
this.mListChild = mListChild; | |
} | |
@Override | |
public List<?> getChildItemList() { | |
return mListChild; | |
} | |
@Override | |
public boolean isInitiallyExpanded() { | |
return false; | |
} | |
} |
Make sure you have returned mListChild in method getChildItemList()
2. Package EXPANDABLES
Open class BiodataChildViewHolder.java. Paste the following code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.androidbie.recyclerviewexapandable.expandables; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.TextView; | |
import android.widget.Toast; | |
import com.androidbie.recyclerviewexapandable.R; | |
import com.androidbie.recyclerviewexapandable.libmoduleExpandable.ViewHolder.ChildViewHolder; | |
import com.androidbie.recyclerviewexapandable.models.BiodataChildModel; | |
/** | |
* Created by putuguna on 04/01/17. | |
*/ | |
public class BiodataChildViewHolder extends ChildViewHolder { | |
private TextView tvStatus; | |
private TextView tvDesc; | |
public BiodataChildViewHolder(View itemView) { | |
super(itemView); | |
tvDesc = (TextView) itemView.findViewById(R.id.text_view_desc); | |
tvStatus = (TextView) itemView.findViewById(R.id.text_view_status); | |
} | |
public void bind(BiodataChildModel biodataChildModel){ | |
Log.d("TAG", "appears " + getAdapterPosition()); | |
tvStatus.setText(biodataChildModel.getStatus()); | |
tvDesc.setText(biodataChildModel.getDescriptions()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.androidbie.recyclerviewexapandable.expandables; | |
import android.graphics.Color; | |
import android.os.Build; | |
import android.view.View; | |
import android.view.animation.RotateAnimation; | |
import android.widget.ImageView; | |
import android.widget.LinearLayout; | |
import android.widget.TextView; | |
import com.androidbie.recyclerviewexapandable.R; | |
import com.androidbie.recyclerviewexapandable.libmoduleExpandable.ViewHolder.ParentViewHolder; | |
import com.androidbie.recyclerviewexapandable.models.BiodataParentModel; | |
/** | |
* Created by putuguna on 04/01/17. | |
*/ | |
public class BiodataParentViewHolder extends ParentViewHolder { | |
private static final float INITIAL_POSITION = 0.0f; | |
private static final float ROTATED_POSITION = 180f; | |
private TextView tvName; | |
private TextView tvAge; | |
private ImageView ivCollapse; | |
private LinearLayout llItem; | |
public BiodataParentViewHolder(View itemView) { | |
super(itemView); | |
tvName = (TextView) itemView.findViewById(R.id.textview_name); | |
tvAge = (TextView) itemView.findViewById(R.id.textview_age); | |
ivCollapse = (ImageView) itemView.findViewById(R.id.image_view_collapse); | |
llItem = (LinearLayout) itemView.findViewById(R.id.ll_item); | |
} | |
public void bind(BiodataParentModel biodataHead){ | |
tvName.setText(biodataHead.getName()); | |
tvAge.setText(biodataHead.getAge()); | |
int position = getAdapterPosition(); | |
if(position%2 == 0) { | |
llItem.setBackgroundColor(Color.parseColor("#ffffff")); | |
} else { | |
llItem.setBackgroundColor(Color.parseColor("#f1f1f1")); | |
} | |
} | |
@Override | |
public void setExpanded(boolean expanded) { | |
super.setExpanded(expanded); | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { | |
if (expanded) { | |
ivCollapse.setImageResource(R.drawable.ic_content_remove); | |
} else { | |
ivCollapse.setImageResource(R.drawable.ic_content_add); | |
} | |
} | |
} | |
@Override | |
public void onExpansionToggled(boolean expanded) { | |
super.onExpansionToggled(expanded); | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { | |
RotateAnimation rotateAnimation; | |
if (expanded) { // rotate clockwise | |
rotateAnimation = new RotateAnimation(ROTATED_POSITION, | |
INITIAL_POSITION, | |
RotateAnimation.RELATIVE_TO_SELF, 0.5f, | |
RotateAnimation.RELATIVE_TO_SELF, 0.5f); | |
} else { // rotate counterclockwise | |
rotateAnimation = new RotateAnimation(-1 * ROTATED_POSITION, | |
INITIAL_POSITION, | |
RotateAnimation.RELATIVE_TO_SELF, 0.5f, | |
RotateAnimation.RELATIVE_TO_SELF, 0.5f); | |
} | |
rotateAnimation.setDuration(200); | |
rotateAnimation.setFillAfter(true); | |
ivCollapse.startAnimation(rotateAnimation); | |
} | |
} | |
} |
- setExpanded(boolean expanded)
- onExpansionToggled(boolean expanded) .
Open class BiodataExpandable.java. Paste the following code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.androidbie.recyclerviewexapandable.expandables; | |
import android.content.Context; | |
import android.support.annotation.NonNull; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import com.androidbie.recyclerviewexapandable.R; | |
import com.androidbie.recyclerviewexapandable.libmoduleExpandable.Adapter.ExpandableRecyclerAdapter; | |
import com.androidbie.recyclerviewexapandable.libmoduleExpandable.Model.ParentListItem; | |
import com.androidbie.recyclerviewexapandable.models.BiodataChildModel; | |
import com.androidbie.recyclerviewexapandable.models.BiodataParentModel; | |
import java.util.List; | |
/** | |
* Created by putuguna on 04/01/17. | |
*/ | |
public class BiodataExpandable extends ExpandableRecyclerAdapter<BiodataParentViewHolder, BiodataChildViewHolder> { | |
private LayoutInflater mLayoutInflater; | |
private Context mContext; | |
public BiodataExpandable(@NonNull List<? extends ParentListItem> parentItemList, Context mContext) { | |
super(parentItemList); | |
this.mLayoutInflater = LayoutInflater.from(mContext); | |
this.mContext = mContext; | |
} | |
@Override | |
public BiodataParentViewHolder onCreateParentViewHolder(ViewGroup parentViewGroup) { | |
View view = mLayoutInflater.inflate(R.layout.item_list_parent, parentViewGroup, false); | |
return new BiodataParentViewHolder(view); | |
} | |
@Override | |
public BiodataChildViewHolder onCreateChildViewHolder(ViewGroup childViewGroup) { | |
View view = mLayoutInflater.inflate(R.layout.item_list_child, childViewGroup, false); | |
return new BiodataChildViewHolder(view); | |
} | |
@Override | |
public void onBindParentViewHolder(BiodataParentViewHolder parentViewHolder, int position, ParentListItem parentListItem) { | |
BiodataParentModel head = (BiodataParentModel) parentListItem; | |
parentViewHolder.bind(head); | |
} | |
@Override | |
public void onBindChildViewHolder(BiodataChildViewHolder childViewHolder, int position, Object childListItem) { | |
BiodataChildModel child = (BiodataChildModel) childListItem; | |
childViewHolder.bind(child); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.androidbie.recyclerviewexapandable; | |
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.recyclerviewexapandable.expandables.BiodataExpandable; | |
import com.androidbie.recyclerviewexapandable.models.BiodataChildModel; | |
import com.androidbie.recyclerviewexapandable.models.BiodataParentModel; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class MainActivity extends AppCompatActivity { | |
private RecyclerView rvBiodata; | |
private BiodataExpandable mBiodataExapandable; | |
List<BiodataParentModel> listModelBiodata = new ArrayList<>(); | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
rvBiodata = (RecyclerView) findViewById(R.id.recyclerview); | |
setData(); | |
rvBiodata.setLayoutManager(new LinearLayoutManager(this)); | |
mBiodataExapandable = new BiodataExpandable(listModelBiodata, this); | |
rvBiodata.setItemAnimator(new DefaultItemAnimator()); | |
rvBiodata.setAdapter(mBiodataExapandable); | |
} | |
private void setData(){ | |
List<BiodataChildModel> mChildBiodata1 = new ArrayList<>(); | |
mChildBiodata1.add(new BiodataChildModel("Single", "I am a free man!")); | |
List<BiodataChildModel> mChildBiodata2 = new ArrayList<>(); | |
mChildBiodata2.add(new BiodataChildModel("Married", "I am a married man!")); | |
List<BiodataChildModel> mChildBiodata3 = new ArrayList<>(); | |
mChildBiodata3.add(new BiodataChildModel("Young", "I am a young man!")); | |
List<BiodataChildModel> mChildBiodata4 = new ArrayList<>(); | |
mChildBiodata4.add(new BiodataChildModel("Married", "I am a married man!")); | |
List<BiodataChildModel> mChildBiodata5 = new ArrayList<>(); | |
mChildBiodata5.add(new BiodataChildModel("Semelekete", "I am a semelekete man!")); | |
BiodataParentModel mHeadBiodata1 = new BiodataParentModel(); | |
mHeadBiodata1.setAge("10"); | |
mHeadBiodata1.setName("Komak"); | |
mHeadBiodata1.setmListChild(mChildBiodata1); | |
BiodataParentModel mHeadBiodata2 = new BiodataParentModel(); | |
mHeadBiodata2.setAge("20"); | |
mHeadBiodata2.setName("Kacang"); | |
mHeadBiodata2.setmListChild(mChildBiodata2); | |
BiodataParentModel mHeadBiodata3 = new BiodataParentModel(); | |
mHeadBiodata3.setAge("15"); | |
mHeadBiodata3.setName("Kare"); | |
mHeadBiodata3.setmListChild(mChildBiodata3); | |
BiodataParentModel mHeadBiodata4 = new BiodataParentModel(); | |
mHeadBiodata4.setAge("24"); | |
mHeadBiodata4.setName("Kedelai"); | |
mHeadBiodata4.setmListChild(mChildBiodata4); | |
BiodataParentModel mHeadBiodata5 = new BiodataParentModel(); | |
mHeadBiodata5.setAge("32"); | |
mHeadBiodata5.setName("Rozan"); | |
mHeadBiodata5.setmListChild(mChildBiodata5); | |
listModelBiodata.add(mHeadBiodata1); | |
listModelBiodata.add(mHeadBiodata2); | |
listModelBiodata.add(mHeadBiodata3); | |
listModelBiodata.add(mHeadBiodata4); | |
listModelBiodata.add(mHeadBiodata5); | |
} | |
} |
Download the project here
1 komentar so far
After 3 days of trying to find a simple, customizable expanding recyclerview (so I could easily add a click listener to each child and properly index it), this was simply the cleanest and most concise example available. libmoduleExpandable was a gold nugget in a bed of rocks!
Thank you!
EmoticonEmoticon