ExpandableListView is kind of advanced version of Listview. You can expand the list items. It is very useful when you have categories and sub categories of data. Here a tutorial using for ExpandableListView with event listener of parent and child list items.
- Create main_activity.xml.
- Create list_group.xml
- Create list_item.xml.
- Create the ExpandableListAdapter.java.
- Create MainActiviy.java.
The file main_activity.xml contain the ExpandableListView tag. list_item.xml and list_gruop.xml has the TextViews for list and sublist.
You can get the complete project at Github Repository. Or you can get the code below in this post.
Here is you main_activiy.xml
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:orientation="vertical" | |
android:padding="8dp" | |
tools:context="com.demo.farooq.sublistlistview.MainActivity"> | |
<ExpandableListView | |
android:id="@+id/simple_expandable_listview" | |
android:layout_width="fill_parent" | |
android:layout_height="wrap_content" | |
android:divider="@color/common_action_bar_splitter" | |
android:dividerHeight="2dp" > | |
</ExpandableListView> | |
</LinearLayout> |
list_group.xml
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:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<TextView | |
android:id="@+id/header" | |
android:layout_width="fill_parent" | |
android:layout_height="wrap_content" | |
android:paddingBottom="2dp" | |
android:paddingTop="2dp" | |
android:paddingLeft="2dp" | |
android:textSize="24sp" | |
android:text="Heading"/> | |
</LinearLayout> |
list_item.xml
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:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<TextView | |
android:id="@+id/child" | |
android:layout_width="fill_parent" | |
android:layout_height="wrap_content" | |
android:paddingBottom="4dp" | |
android:paddingTop="4dp" | |
android:paddingLeft="12dp" | |
android:textSize="18sp" | |
android:text="Item"/> | |
</LinearLayout> |
ExpandableListAdapter.java
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.demo.farooq.sublistlistview; | |
import android.content.Context; | |
import android.graphics.Typeface; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.BaseExpandableListAdapter; | |
import android.widget.TextView; | |
import java.util.HashMap; | |
import java.util.List; | |
/** | |
* Created by farooq on 1/4/2017. | |
*/ | |
public class ExpandableListAdapter extends BaseExpandableListAdapter { | |
private Context _context; | |
private List<String> header; // header titles | |
// Child data in format of header title, child title | |
private HashMap<String, List<String>> child; | |
public ExpandableListAdapter(Context context, List<String> listDataHeader, HashMap<String, List<String>> listChildData) { | |
this._context = context; | |
this.header = listDataHeader; | |
this.child = listChildData; | |
} | |
@Override | |
public int getGroupCount() { | |
// Get header size | |
return this.header.size(); | |
} | |
@Override | |
public int getChildrenCount(int groupPosition) { | |
// return children count | |
return this.child.get(this.header.get(groupPosition)).size(); | |
} | |
@Override | |
public Object getGroup(int groupPosition) { | |
// Get header position | |
return this.header.get(groupPosition); | |
} | |
@Override | |
public Object getChild(int groupPosition, int childPosition) { | |
// This will return the child | |
return this.child.get(this.header.get(groupPosition)).get(childPosition); | |
} | |
@Override | |
public long getGroupId(int groupPosition) { | |
return groupPosition; | |
} | |
@Override | |
public long getChildId(int groupPosition, int childPosition) { | |
return childPosition; | |
} | |
@Override | |
public boolean hasStableIds() { | |
// TODO Auto-generated method stub | |
return false; | |
} | |
@Override | |
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { | |
// Getting header title | |
String headerTitle = (String) getGroup(groupPosition); | |
// Inflating header layout and setting text | |
if (convertView == null) { | |
LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); | |
convertView = infalInflater.inflate(R.layout.list_group, parent, false); | |
} | |
//set content for the parent views | |
TextView header_text = (TextView) convertView.findViewById(R.id.header); | |
header_text.setText(headerTitle); | |
// If group is expanded then change the text into bold and change the | |
// icon | |
if (isExpanded) { | |
header_text.setTypeface(null, Typeface.BOLD); | |
header_text.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.up, 0); | |
} else { | |
// If group is not expanded then change the text back into normal | |
// and change the icon | |
header_text.setTypeface(null, Typeface.NORMAL); | |
header_text.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.down, 0); | |
} | |
return convertView; | |
} | |
@Override | |
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { | |
// Getting child text | |
final String childText = (String) getChild(groupPosition, childPosition); | |
// Inflating child layout and setting textview | |
if (convertView == null) { | |
LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); | |
convertView = infalInflater.inflate(R.layout.list_item, parent, false); | |
} | |
//set content in the child views | |
TextView child_text = (TextView) convertView.findViewById(R.id.child); | |
child_text.setText(childText); | |
return convertView; | |
} | |
@Override | |
public boolean isChildSelectable(int groupPosition, int childPosition) { | |
// TODO Auto-generated method stub | |
return true; | |
} | |
} |
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.demo.farooq.sublistlistview; | |
import android.os.Bundle; | |
import android.support.v7.app.AppCompatActivity; | |
import android.support.v7.widget.Toolbar; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.widget.ExpandableListView; | |
import android.widget.ExpandableListView.OnGroupClickListener; | |
import android.widget.ExpandableListView.OnGroupExpandListener; | |
import android.widget.Toast; | |
import com.demo.farooq.sublistlistview.ExpandableListAdapter; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import static android.widget.ExpandableListView.*; | |
/** | |
* Created by farooq on 1/4/2017. | |
*/ | |
public class MainActivity extends AppCompatActivity { | |
private static ExpandableListView expandableListView; | |
private static ExpandableListAdapter adapter; | |
HashMap<String, List<String>> hashMap; | |
ArrayList<String> header; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
expandableListView = (ExpandableListView) findViewById(R.id.simple_expandable_listview); | |
// Setting group indicator null for custom indicator | |
expandableListView.setGroupIndicator(null); | |
setItems(); | |
adapter = new ExpandableListAdapter(MainActivity.this, header, hashMap); | |
// Setting adpater for expandablelistview | |
expandableListView.setAdapter(adapter); | |
/* | |
You can add listeners for the item clicks | |
*/ | |
expandableListView.setOnGroupClickListener(new OnGroupClickListener() { | |
@Override | |
public boolean onGroupClick(ExpandableListView parent, View v, | |
int groupPosition, long id) { | |
return false; | |
} | |
}); | |
// Listview Group expanded listener | |
expandableListView.setOnGroupExpandListener(new OnGroupExpandListener() { | |
@Override | |
public void onGroupExpand(int groupPosition) { | |
Toast.makeText(getApplicationContext(), | |
header.get(groupPosition) + " Expanded", | |
Toast.LENGTH_SHORT).show(); | |
} | |
}); | |
// Listview Group collasped listener | |
expandableListView.setOnGroupCollapseListener(new OnGroupCollapseListener() { | |
@Override | |
public void onGroupCollapse(int groupPosition) { | |
Toast.makeText(getApplicationContext(), | |
header.get(groupPosition) + " Collapsed", | |
Toast.LENGTH_SHORT).show(); | |
} | |
}); | |
// Listview on child click listener | |
expandableListView.setOnChildClickListener(new OnChildClickListener() { | |
@Override | |
public boolean onChildClick(ExpandableListView parent, View v, | |
int groupPosition, int childPosition, long id) { | |
Toast.makeText( | |
getApplicationContext(), | |
header.get(groupPosition) | |
+ " : " | |
+ hashMap.get( | |
header.get(groupPosition)).get( | |
childPosition), Toast.LENGTH_SHORT) | |
.show(); | |
return false; | |
} | |
}); | |
} | |
// Setting headers and childs to expandable listview | |
void setItems() { | |
// Array list for header | |
header = new ArrayList<String>(); | |
// Array list for child items | |
List<String> child1 = new ArrayList<String>(); | |
List<String> child2 = new ArrayList<String>(); | |
List<String> child3 = new ArrayList<String>(); | |
List<String> child4 = new ArrayList<String>(); | |
// Hash map for both header and child | |
hashMap = new HashMap<String, List<String>>(); | |
// Adding headers to list | |
for (int i = 1; i < 5; i++) { | |
header.add("Group " + i); | |
} | |
// Adding child data | |
for (int i = 1; i < 5; i++) { | |
child1.add("Child" + i); | |
} | |
// Adding child data | |
for (int i = 1; i < 5; i++) { | |
child2.add("Child" + i); | |
} | |
// Adding child data | |
for (int i = 1; i < 6; i++) { | |
child3.add("Child" + i); | |
} | |
// Adding child data | |
for (int i = 1; i < 7; i++) { | |
child4.add("Child" + i); | |
} | |
// Adding header and childs to hash map | |
hashMap.put(header.get(0), child1); | |
hashMap.put(header.get(1), child2); | |
hashMap.put(header.get(2), child3); | |
hashMap.put(header.get(3), child4); | |
} | |
} |
Really a great and simple tutorial for beginners. Thumbs up (Y)
ReplyDeletemeow...
ReplyDeleteYour content is excellent but with pics and videos,
ReplyDeletethis blog could certainly be one of the best in its field.
Excellent blog!
KissAnime