我在尝试这样做时遇到了问题。我似乎无法做到正确,我想控制那个父母的每个父母+孩子。 ExpandableListView让我很头疼。 包评论;
public class CommentsExpandableListAdapter extends BaseExpandableListAdapter {
private Activity context;
private Map<String, List<String>> comments_feed_collection;
private List<String> group_list;
private boolean a_comment = false;
public CommentsExpandableListAdapter(Activity context, List<String> group_list,
Map<String, List<String>> comments_feed_collection) {
this.context = context;
this.comments_feed_collection = comments_feed_collection;
this.group_list = group_list;
}
public Object getChild(int groupPosition, int childPosition) {
return comments_feed_collection.get(group_list.get(groupPosition)).get(childPosition);
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String incoming_text = (String) getChild(groupPosition, childPosition);
LayoutInflater inflater = context.getLayoutInflater();
if (convertView == null) {
//first view
if(childPosition==0 && groupPosition==0) {
convertView = inflater.inflate(R.layout.description_of_ads_expandable_list, null);
TextView description_child = (TextView) convertView.findViewById(R.id.description_of_ads_expandable_list_child_text_view);
description_child.setText(incoming_text);
}else if(childPosition==0 && groupPosition==1){
//second view view
convertView = inflater.inflate(R.layout.comments_create_comment, null);
}else if(childPosition>=1 && groupPosition>=1){
//thrid view
convertView = inflater.inflate(R.layout.comments_expandable_list_child, null);
}
}
return convertView;
}
public int getChildrenCount(int groupPosition) {
return comments_feed_collection.get(group_list.get(groupPosition)).size();
}
public Object getGroup(int groupPosition) {
return group_list.get(groupPosition);
}
public int getGroupCount() {
return group_list.size();
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String incoming_text = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.expandable_list_single_item,
null);
}
TextView item = (TextView) convertView.findViewById(R.id.expandable_list_single_item_text_view_group);
item.setTypeface(null, Typeface.BOLD);
item.setText(incoming_text);
return convertView;
}
public boolean hasStableIds() {
return true;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
@Override
public int getChildTypeCount() {
return 3;
}
@Override
public int getGroupType(int groupPosition) {
return super.getGroupType(groupPosition);
}
@Override
public int getGroupTypeCount() {
return 3;
}
}
答案 0 :(得分:24)
我认为你的主要错误在于public View getChildView(...)
:
if (convertView == null)
实际上只到达一次,当您加载标记为第一个视图的条件时。因此,您要对第一个布局R.layout.description_of_ads_expandable_list
进行充气,并将其重新用于列表中的所有其他行。childPosition==1 && groupPosition==0
,您认为会发生什么? Booom! NullPointerException如果您的数据源还有一个元素用于第一组。首先是第一件事;如果要对ExpandableListView的不同组/子项使用不同的布局,则应完全实现HeterogeneousExpandableList interface。
然后使用该接口处理应加载布局的条件。
最后处理public View getChildView(...)
上的重用视图问题。
既然我是一个好人,这里有一个应该帮助你的片段(基于你发布的适配器):
public class CommentsExpandableListAdapter extends BaseExpandableListAdapter {
// 4 Child types
private static final int CHILD_TYPE_1 = 0;
private static final int CHILD_TYPE_2 = 1;
private static final int CHILD_TYPE_3 = 2;
private static final int CHILD_TYPE_UNDEFINED = 3;
// 3 Group types
private static final int GROUP_TYPE_1 = 0;
private static final int GROUP_TYPE_2 = 1;
private static final int GROUP_TYPE_3 = 2;
private Activity context;
private Map<String, List<String>> comments_feed_collection;
private List<String> group_list;
public CommentsExpandableListAdapter(Activity context, List<String> group_list,
Map<String, List<String>> comments_feed_collection) {
this.context = context;
this.comments_feed_collection = comments_feed_collection;
this.group_list = group_list;
}
public Object getChild(int groupPosition, int childPosition) {
return comments_feed_collection.get(group_list.get(groupPosition)).get(childPosition);
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
final String incoming_text = (String) getChild(groupPosition, childPosition);
LayoutInflater inflater = context.getLayoutInflater();
int childType = getChildType(groupPosition, childPosition);
// We need to create a new "cell container"
if (convertView == null || convertView.getTag() != childType) {
switch (childType) {
case CHILD_TYPE_1:
convertView = inflater.inflate(R.layout.description_of_ads_expandable_list, null);
convertView.setTag(childType);
break;
case CHILD_TYPE_2:
convertView = inflater.inflate(R.layout.comments_create_comment, null);
convertView.setTag(childType);
break;
case CHILD_TYPE_3:
convertView = inflater.inflate(R.layout.comments_expandable_list_child, null);
convertView.setTag(childType);
break;
case CHILD_TYPE_UNDEFINED:
convertView = inflater.inflate(R.layout.comments_undefined, null);
convertView.setTag(childType);
break;
default:
// Maybe we should implement a default behaviour but it should be ok we know there are 4 child types right?
break;
}
}
// We'll reuse the existing one
else {
// There is nothing to do here really we just need to set the content of view which we do in both cases
}
switch (childType) {
case CHILD_TYPE_1:
TextView description_child = (TextView) convertView.findViewById(R.id.description_of_ads_expandable_list_child_text_view);
description_child.setText(incoming_text);
break;
case CHILD_TYPE_2:
//Define how to render the data on the CHILD_TYPE_2 layout
break;
case CHILD_TYPE_3:
//Define how to render the data on the CHILD_TYPE_3 layout
break;
case CHILD_TYPE_UNDEFINED:
//Define how to render the data on the CHILD_TYPE_UNDEFINED layout
break;
}
return convertView;
}
public int getChildrenCount(int groupPosition) {
String groupName = group_list.get(groupPosition);
List<String> groupContent = comments_feed_collection.get(groupName);
return groupContent.size();
}
public Object getGroup(int groupPosition) {
return group_list.get(groupPosition);
}
public int getGroupCount() {
return group_list.size();
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
final String incoming_text = (String) getGroup(groupPosition);
int groupType = getGroupType(groupPosition);
// We need to create a new "cell container"
if (convertView == null || convertView.getTag() != groupType) {
switch (groupType) {
case GROUP_TYPE_1 :
convertView = inflater.inflate(R.layout.expandable_list_single_item, null);
break;
case GROUP_TYPE_2:
// Am using the same layout cause am lasy and don't wanna create other ones but theses should be different
// or the group type shouldnt exist
convertView = inflater.inflate(R.layout.expandable_list_single_item, null);
break;
case GROUP_TYPE_3:
// Am using the same layout cause am lasy and don't wanna create other ones but theses should be different
// or the group type shouldnt exist
convertView = inflater.inflate(R.layout.expandable_list_single_item, null);
break;
default:
// Maybe we should implement a default behaviour but it should be ok we know there are 3 group types right?
break;
}
}
// We'll reuse the existing one
else {
// There is nothing to do here really we just need to set the content of view which we do in both cases
}
switch (groupType) {
case GROUP_TYPE_1 :
TextView item = (TextView) convertView.findViewById(R.id.expandable_list_single_item_text_view_group);
item.setTypeface(null, Typeface.BOLD);
item.setText(incoming_text);
break;
case GROUP_TYPE_2:
//TODO: Define how to render the data on the GROUPE_TYPE_2 layout
// Since i use the same layout as GROUPE_TYPE_1 i could do the same thing as above but i choose to do nothing
break;
case GROUP_TYPE_3:
//TODO: Define how to render the data on the GROUPE_TYPE_3 layout
// Since i use the same layout as GROUPE_TYPE_1 i could do the same thing as above but i choose to do nothing
break;
default:
// Maybe we should implement a default behaviour but it should be ok we know there are 3 group types right?
break;
}
return convertView;
}
public boolean hasStableIds() {
return true;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
@Override
public int getChildTypeCount() {
return 4; // I defined 4 child types (CHILD_TYPE_1, CHILD_TYPE_2, CHILD_TYPE_3, CHILD_TYPE_UNDEFINED)
}
@Override
public int getGroupTypeCount() {
return 3; // I defined 3 groups types (GROUP_TYPE_1, GROUP_TYPE_2, GROUP_TYPE_3)
}
@Override
public int getGroupType(int groupPosition) {
switch (groupPosition) {
case 0:
return GROUP_TYPE_1;
case 1:
return GROUP_TYPE_1;
case 2:
return GROUP_TYPE_2;
default:
return GROUP_TYPE_3;
}
}
@Override
public int getChildType(int groupPosition, int childPosition) {
switch (groupPosition) {
case 0:
switch (childPosition) {
case 0:
return CHILD_TYPE_1;
case 1:
return CHILD_TYPE_UNDEFINED;
case 2:
return CHILD_TYPE_UNDEFINED;
}
break;
case 1:
switch (childPosition) {
case 0:
return CHILD_TYPE_2;
case 1:
return CHILD_TYPE_3;
case 2:
return CHILD_TYPE_3;
}
break;
default:
return CHILD_TYPE_UNDEFINED;
}
return CHILD_TYPE_UNDEFINED;
}
}
这就是它的样子:
希望这会有所帮助,让我知道它是否确实存在。