我正在尝试在android中实现ExpandableListView
。但我没有找到任何好的教程。
我必须在父视图上绘制一个复选框和一个textview。在子视图上,第一个项目包含一个复选框和一个图像视图,最后三个是文本视图。任何人都可以帮助我如何延长SimpleExpandableListAdapter
?
答案 0 :(得分:3)
查找自定义ExpandableListView
适配器的示例的第一个地方是随SDK提供的示例应用程序,您可以在以下位置找到:
{sdk_root} /samples/platform-xx/ApiDemos/src/com/example/android/apis/view/ExpandableListView1.java
对于问题的情况(所有组的布局相同,后面跟着两种类型的子行布局),您可以找到自定义适配器的示例。请注意,我扩展了BaseExpandableListAdapter
,我已经这样做了,因为扩展SimpleExpandableListAdapter
仅适用于小的更改(因为它的名称建议用于解决基本使用方案)。
private static class CustomExpandableAdapter extends
BaseExpandableListAdapter {
// identifiers for our two types of rows, if the child rows are the same
// this aren't required.
private static final int FIRST_CHILD = 0;
private static final int OTHER_CHILD = 1;
private LayoutInflater mInflater;
private List<HashMap<String, Object>> mGroupData;
private List<ArrayList<HashMap<String, Object>>> mChildData;
public CustomExpandableAdapter(Context context,
List<HashMap<String, Object>> makeGroupData,
List<ArrayList<HashMap<String, Object>>> makeChildData) {
mInflater = LayoutInflater.from(context);
mGroupData = makeGroupData;
mChildData = makeChildData;
}
@Override
public int getChildType(int groupPosition, int childPosition) {
if (childPosition == 0) {
return FIRST_CHILD; // this is the first child row so return
// FIRST_CHILD as the type of row
}
return OTHER_CHILD;
}
@Override
public int getChildTypeCount() {
return 2; // two types of children rows
}
@Override
public HashMap<String, Object> getChild(int groupPosition,
int childPosition) {
return mChildData.get(groupPosition).get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
// if we don't have a recycled row available inflate one BASED on
// the type of row this child should have.
int type = getChildType(groupPosition, childPosition);
ChildViewHolder holder;
if (convertView == null) {
holder = new ChildViewHolder();
switch (type) {
case FIRST_CHILD:
convertView = mInflater.inflate(
R.layout.view_expandlistchild, parent, false); // contains only an ImageView and a CheckBox
holder.image = (ImageView) convertView
.findViewById(R.id.imageViewChild);
holder.check = (CheckBox) convertView
.findViewById(R.id.checkBoxChild);
break;
case OTHER_CHILD:
convertView = mInflater.inflate(
android.R.layout.simple_list_item_1, parent, false); // contains only a TextView
holder.text = (TextView) convertView
.findViewById(android.R.id.text1);
break;
}
convertView.setTag(holder);
} else {
holder = (ChildViewHolder) convertView.getTag();
}
final HashMap<String, Object> item = getChild(groupPosition,
childPosition);
// we set the data on the row based on the type of the row(so we
// access only the views we do have in the layout)
switch (type) {
case FIRST_CHILD:
holder.image.setImageResource((Integer) item.get(CHILD_IMAGE));
// pass in the checked listener this as a tag so we can identify
// the proper data position and update it
holder.check.setTag(new PositionsWrapper(groupPosition,
childPosition));
holder.check
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(
CompoundButton buttonView, boolean isChecked) {
// set the new status of the checked item
// otherwise the status will be erased as the
// user scrolls down and up
PositionsWrapper pw = (PositionsWrapper) buttonView
.getTag();
mChildData.get(pw.groupPosition)
.get(pw.childPosition)
.put(CHILD_STATUS, isChecked);
}
});
holder.check.setChecked((Boolean) item.get(CHILD_STATUS));
break;
case OTHER_CHILD:
holder.text.setText((CharSequence) item.get(CHILD_TEXT));
break;
}
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return mChildData.get(groupPosition).size();
}
@Override
public HashMap<String, Object> getGroup(int groupPosition) {
return mGroupData.get(groupPosition);
}
@Override
public int getGroupCount() {
return mGroupData.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
// normal row building like in any custom adapter
GroupViewHolder holder;
if (convertView == null) {
holder = new GroupViewHolder();
convertView = mInflater.inflate(R.layout.view_expandlistgroup,
parent, false); // contains a TextView and a CheckBox
holder.text = (TextView) convertView
.findViewById(R.id.textGroup);
holder.check = (CheckBox) convertView
.findViewById(R.id.checkBoxGroup);
convertView.setTag(holder);
} else {
holder = (GroupViewHolder) convertView.getTag();
}
final HashMap<String, Object> item = getGroup(groupPosition);
holder.text.setText((CharSequence) item.get(GROUP_TEXT));
holder.check.setTag(Integer.valueOf(groupPosition));
holder.check
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// again, save the new status in the data list so we
// keep the status as the user scrolls
Integer groupPosition = (Integer) buttonView
.getTag();
mGroupData.get(groupPosition).put(GROUP_STATUS,
isChecked);
}
});
holder.check.setChecked((Boolean) item.get(GROUP_STATUS));
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
/**
* Simple class that wraps two integers representing the group and child
* row position.
*
* @author Luksprog
*
*/
private static class PositionsWrapper {
int groupPosition;
int childPosition;
PositionsWrapper(int groupPosition, int childPosition) {
this.groupPosition = groupPosition;
this.childPosition = childPosition;
}
}
// basic ViewHolder classes
private static class GroupViewHolder {
TextView text;
CheckBox check;
}
private static class ChildViewHolder {
ImageView image;
CheckBox check;
TextView text;
}
}
可以找到完整的样本here。