Reputation: 1499
I am trying to implement the Expandable listview which consists different types of views such as textviews, editboxes and dropdowns as its childs as below.
Personal Info (Header)
Name (editbox)
Gender (spinner)
Age (editbox)
Address (Header)
Province (dropdown)
street (Editbox)
textview
Here is my adapter code. (for only editbox type child)
public class ExpandableListAdapter extends BaseExpandableListAdapter implements
TextWatcher {
private Context _context;
private List<String> _listDataHeader; // header titles
// child data in format of header title, child title
private HashMap<String, List<String>> _listDataChild;
private ArrayList<EditText> editTextList = new ArrayList<EditText>();
String name, purpose;
public ExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listChildData) {
this._context = context;
this._listDataHeader = listDataHeader;
this._listDataChild = listChildData;
}
@Override
public Object getChild(int groupPosition, int childPosititon) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition))
.get(childPosititon);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition, childPosition);
String header = _listDataHeader.get(groupPosition);
System.out.println("Header: " + header);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.listitem, null);
}
TextView txtListChild = (TextView) convertView
.findViewById(R.id.lblListItem);
txtListChild.setText(childText);
EditText editetext = (EditText) convertView
.findViewById(R.id.lblListItemEditext);
editetext.addTextChangedListener(this);
editTextList.add(editetext);
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition))
.size();
}
@Override
public Object getGroup(int groupPosition) {
return this._listDataHeader.get(groupPosition);
}
@Override
public int getGroupCount() {
return this._listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.listgroup, null);
}
TextView lblListHeader = (TextView) convertView
.findViewById(R.id.lblListHeader);
lblListHeader.setTypeface(null, Typeface.BOLD);
lblListHeader.setText(headerTitle);
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
}
screenshot:
I have gone through different websites, but i found the solution for only that type of expandable listviews which consists only one type of view.
Thanks.
Upvotes: 0
Views: 2844
Reputation: 1670
Study the getView() method of adapter below, and you would be able to design the adapter however you want,
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition, childPosition);
String header = _listDataHeader.get(groupPosition);
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//If your groups are fixed then we can differentiate using groupPosition otherwise
// we will have to compare the groupHeader title(which is a bit low performance)
//Lets say we have three group headers as Personal Info, Contact Detail and Family Info
// so we know their positions as 0,1 & 2
switch (groupPosition){
case 0 :
//Now lets say we have fixed childViews as First Name, Middle Name, Last Name, Gende and Religion
//with positions 0,1,2,3,4,5
switch (childPosition){
case 0 :
convertView = infalInflater.inflate(R.layout.listitem_first_name, null);
TextView txtListChild = (TextView) convertView.findViewById(R.id.lblListItem);
txtListChild.setText(childText);
EditText editetext = (EditText) convertView.findViewById(R.id.lblListItemEditext);
editetext.addTextChangedListener(this);
editTextList.add(editetext);
break;
case 1 :
convertView = infalInflater.inflate(R.layout.listitem_last_name, null);
TextView txtListChild2 = (TextView) convertView.findViewById(R.id.lblListItemTextView);
txtListChild2.setText(childText);
break;
case 2 :
convertView = infalInflater.inflate(R.layout.listitem_gender, null);
Spinner genderSpinner = (Spinner) convertView.findViewById(R.id.lblListItemSpinner_);
genderSpinner.setSelection(0); //check for gender and select accordingly
break;
}
break;
case 1 :
// with reference to above case 0 code this
break;
case 2 :
// with reference to above case 0 code this
break;
}
return convertView;
}
The issue with this is I have not recycled views, which may cause performance issues while scrolling so you try to use a viewHolder class inside the adapter and with the help of id of viewHolder we can check, which convertview we have and accordingly decide where to reuse it.
Upvotes: 1
Reputation: 393
My suggestion would be to develop multiples layouts and inflate them according to their position. Here is some pseudo code:
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition, childPosition);
String header = _listDataHeader.get(groupPosition);
System.out.println("Header: " + header);
if (convertView == null) {
if(child refers to dropdown layout){
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.dropdown_layout, null);
do code for dropdown
}
if(child refers to spinner layout{
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.spinner_layout, null);
do code for spinner
}
... test your other layouts
}
return convertView;
}
Hope it helps.
Upvotes: 0
Reputation: 2100
You can achieve this by combining different adapters (with different views) into one single adapter. You need to use Commons Guy's Merge Adapter.
You can find all the information here. Hope it helps.
https://github.com/commonsguy/cwac-merge
Upvotes: 0