不同的子布局不同群体ExpandableListView不同、布局、群体、ExpandableListView

2023-09-07 00:28:26 作者:谁主沉浮

我一直在试图做到这一点的问题。我似乎无法得到它的权利,我想控制每个父母+孩子的父母。 ExpandableListView已经让我头疼。包意见;

 公共类CommentsExpandableListAdapter扩展BaseExpandableListAdapter {私人活动范围内;私人地图<字符串列表<串GT;> comments_feed_collection;私人列表<串GT; GROUP_LIST;私人布尔a_comment = FALSE;公共CommentsExpandableListAdapter(Activity上下文,列表<串GT; group_list中,                             地图<字符串列表<串GT;> comments_feed_collection){    this.context =背景;    this.comments_feed_collection = comments_feed_collection;    this.group_list = GROUP_LIST;}公共对象getChild(INT groupPosition,诠释childPosition){    返回comments_feed_collection.get(group_list.get(groupPosition))获得(childPosition)。}众长getChildId(INT groupPosition,诠释childPosition){    返回childPosition;}公共查看getChildView(最终诠释groupPosition,最终诠释childPosition,                         布尔isLastChild,查看convertView,父母的ViewGroup){    最后弦乐incoming_text =(字符串)getChild(groupPosition,childPosition);    LayoutInflater吹气= context.getLayoutInflater();    如果(convertView == NULL){        //第一个视图        如果(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);        }否则如果(childPosition == 0安培;&安培; groupPosition == 1){            //第二种观点认为            convertView = inflater.inflate(R.layout.comments_create_comment,NULL);        }否则如果(childPosition> = 1和;&放大器; groupPosition> = 1){            // THRID视图            convertView = inflater.inflate(R.layout.comments_expandable_list_child,NULL);        }    }    返回convertView;}公众诠释getChildrenCount(INT groupPosition){    返回comments_feed_collection.get(group_list.get(groupPosition))的大小()。}公共对象getGroup(INT groupPosition){    返回group_list.get(groupPosition);}公众诠释getGroupCount(){    返回group_list.size();}众长getGroupId(INT groupPosition){    返回groupPosition;}公共查看getGroupView(INT groupPosition,布尔isExpanded,                         查看convertView,父母的ViewGroup){    字符串incoming_text =(字符串)getGroup(groupPosition);    如果(convertView == NULL){        LayoutInflater infalInflater =(LayoutInflater)上下文                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);        convertView = infalInflater.inflate(R.layout.expandable_list_single_item,                空值);    }    TextView的项目=(TextView中)convertView.findViewById(R.id.expandable_list_single_item_text_view_group);    item.setTypeface(NULL,Typeface.BOLD);    item.setText(incoming_text);    返回convertView;}公共布尔hasStableIds(){    返回true;}公共布尔isChildSelectable(INT groupPosition,诠释childPosition){    返回true;}@覆盖公众诠释getChildTypeCount(){    返回3;}@覆盖公众诠释getGroupType(INT groupPosition){    返回super.getGroupType(groupPosition);}@覆盖公众诠释getGroupTypeCount(){    返回3;}} 

解决方案

我觉得你的主要错误在于公开查看getChildView(...)

条件如果(convertView == NULL)实际上只达到了一次,当你加载你标记为第一种观点的一个的。那么,你是充气的第一个布局 R.layout.description_of_ads_expandable_list 和重用它在你的列表中的所有其他行。您正在检查子视图的负载类型的方式是危险的,因为它是不完整的。你觉得会happend如果 childPosition == 1安培;&安培; groupPosition == 0 ? Booom! NullPointerException - 如果您的数据源具有第一组多了一个元素。

所以,首先第一件事情;你要全面贯彻 HeterogeneousExpandableList接口的,如果你要使用不同的不同的布局您ExpandableListView组/儿童。

然后,使用上的布局应加载的条件接口的工作。

最后就重用视图问题上工作公开查看getChildView(...)

由于是这里的好人是一个片段,它可以帮助你(你根据张贴在适配器上):

 公共类CommentsExpandableListAdapter扩展BaseExpandableListAdapter {    // 4种儿童    私有静态最终诠释CHILD_TYPE_1 = 0;    私有静态最终诠释CHILD_TYPE_2 = 1;    私有静态最终诠释CHILD_TYPE_3 = 2;    私有静态最终诠释CHILD_TYPE_UNDEFINED = 3;    // 3组类型    私有静态最终诠释GROUP_TYPE_1 = 0;    私有静态最终诠释GROUP_TYPE_2 = 1;    私有静态最终诠释GROUP_TYPE_3 = 2;    私人活动范围内;    私人地图<字符串列表<串GT;> comments_feed_collection;    私人列表<串GT; GROUP_LIST;    公共CommentsExpandableListAdapter(Activity上下文,列表<串GT; group_list中,                                         地图<字符串列表<串GT;> comments_feed_collection){        this.context =背景;        this.comments_feed_collection = comments_feed_collection;        this.group_list = GROUP_LIST;    }    公共对象getChild(INT groupPosition,诠释childPosition){        返回comments_feed_collection.get(group_list.get(groupPosition))获得(childPosition)。    }    众长getChildId(INT groupPosition,诠释childPosition){        返回childPosition;    }    公共查看getChildView(最终诠释groupPosition,最终诠释childPosition,布尔isLastChild,查看convertView,父母的ViewGroup){        最后弦乐incoming_text =(字符串)getChild(groupPosition,childPosition);        LayoutInflater吹气= context.getLayoutInflater();        INT childType = getChildType(groupPosition,childPosition);        //我们需要建立一个新的电池容器        如果(convertView == NULL || convertView.getTag()!= childType){            开关(childType){                案例CHILD_TYPE_1:                    convertView = inflater.inflate(R.layout.description_of_ads_expandable_list,NULL);                    convertView.setTag(childType);                    打破;                案例CHILD_TYPE_2:                    convertView = inflater.inflate(R.layout.comments_create_comment,NULL);                    convertView.setTag(childType);                    打破;                案例CHILD_TYPE_3:                    convertView = inflater.inflate(R.layout.comments_expandable_list_child,NULL);                    convertView.setTag(childType);                    打破;                案例CHILD_TYPE_UNDEFINED:                    convertView = inflater.inflate(R.layout.comments_undefined,NULL);                    convertView.setTag(childType);                    打破;                默认:                    //也许我们应该实现一个默认行为,但它应该是好的,我们知道有4个孩子的类型吗?                    打破;            }        }        //我们将重用现有的        其他{            //没有什么在这里做我们真的只需要设置来看,我们在这两种情况下做内容        }        开关(childType){            案例CHILD_TYPE_1:                TextView的description_child =(TextView中)convertView.findViewById(R.id.description_of_ads_expandable_list_child_text_view);                description_child.setText(incoming_text);                打破;            案例CHILD_TYPE_2:                //定义如何呈现在CHILD_TYPE_2布局数据                打破;            案例CHILD_TYPE_3:                //定义如何呈现在CHILD_TYPE_3布局数据                打破;            案例CHILD_TYPE_UNDEFINED:                //定义如何呈现在CHILD_TYPE_UNDEFINED布局数据                打破;        }        返回convertView;    }    公众诠释getChildrenCount(INT groupPosition){        串组名= group_list.get(groupPosition);        清单<串GT; groupContent = comments_feed_collection.get(组名);        返回groupContent.size();    }    公共对象getGroup(INT groupPosition){        返回group_list.get(groupPosition);    }    公众诠释getGroupCount(){        返回group_list.size();    }    众长getGroupId(INT groupPosition){        返回groupPosition;    }    公共查看getGroupView(INT groupPosition,布尔isExpanded,查看convertView,父母的ViewGroup){        LayoutInflater吹气= context.getLayoutInflater();        最后弦乐incoming_text =(字符串)getGroup(groupPosition);        INT groupType = getGroupType(groupPosition);        //我们需要建立一个新的电池容器        如果(convertView == NULL || convertView.getTag()!= groupType){            开关(groupType){                案例GROUP_TYPE_1:                    convertView = inflater.inflate(R.layout.expandable_list_single_item,NULL);                    打破;                案例GROUP_TYPE_2:                    //现在用的是相同的布局事业上午镭石光电和不想创建其他的,但论文应该是不同的                    //或组类型不应该存在                    convertView = inflater.inflate(R.layout.expandable_list_single_item,NULL);                    打破;                案例GROUP_TYPE_3:                    //现在用的是相同的布局事业上午镭石光电和不想创建其他的,但论文应该是不同的                    //或组类型不应该存在                    convertView = inflater.inflate(R.layout.expandable_list_single_item,NULL);                    打破;                默认:                    //也许我们应该实现一个默认的行为,但它应该是确定我们知道有3组类型吧?                    打破;            }        }        //我们将重用现有的        其他{            //没有什么在这里做我们真的只需要设置来看,我们在这两种情况下做内容        }        开关(groupType){            案例GROUP_TYPE_1:                TextView的项目=(TextView中)convertView.findViewById(R.id.expandable_list_single_item_text_view_group);                item.setTypeface(NULL,Typeface.BOLD);                item.setText(incoming_text);                打破;            案例GROUP_TYPE_2:                // TODO:定义如何呈现在GROUPE_TYPE_2布局数据                //由于我使用的布局相同GROUPE_TYPE_1我可以做同样的事情上面一样,但我选择什么都不做                打破;            案例GROUP_TYPE_3:                // TODO:定义如何呈现在GROUPE_TYPE_3布局数据                //由于我使用的布局相同GROUPE_TYPE_1我可以做同样的事情上面一样,但我选择什么都不做                打破;            默认:                //也许我们应该实现一个默认的行为,但它应该是确定我们知道有3组类型吧?                打破;        }        返回convertView;    }    公共布尔hasStableIds(){        返回true;    }    公共布尔isChildSelectable(INT groupPosition,诠释childPosition){        返回false;    }    @覆盖    公众诠释getChildTypeCount(){        返回4; //我定义了4个孩子的类型(CHILD_TYPE_1,CHILD_TYPE_2,CHILD_TYPE_3,CHILD_TYPE_UNDEFINED)    }    @覆盖    公众诠释getGroupTypeCount(){        返回3; //我定义了3种组(GROUP_TYPE_1,GROUP_TYPE_2,GROUP_TYPE_3)    }    @覆盖    公众诠释getGroupType(INT groupPosition){        开关(groupPosition){            情况下0:                返回GROUP_TYPE_1;            情况1:                返回GROUP_TYPE_1;            案例2:                返回GROUP_TYPE_2;            默认:                返回GROUP_TYPE_3;        }    }    @覆盖    公众诠释getChildType(INT groupPosition,诠释childPosition){        开关(groupPosition){            情况下0:                开关(childPosition){                    情况下0:                        返回CHILD_TYPE_1;                    情况1:                        返回CHILD_TYPE_UNDEFINED;                    案例2:                        返回CHILD_TYPE_UNDEFINED;                }                打破;            情况1:                开关(childPosition){                    情况下0:                        返回CHILD_TYPE_2;                    情况1:                        返回CHILD_TYPE_3;                    案例2:                        返回CHILD_TYPE_3;                }                打破;            默认:                返回CHILD_TYPE_UNDEFINED;        }        返回CHILD_TYPE_UNDEFINED;    }} 

这是它的样子:

希望这会有所帮助,让我知道,如果它确实/犯规。

Android ExpandableListView 一

I've been having issues trying to do this. I can't seem to get it right, I want to control each parent + children of that parent. ExpandableListView has been giving me a headache. package comments;

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;
}
}

解决方案

I think your main mistake resides in public View getChildView(...) :

The condition if (convertView == null) is actually only reached once and that's when you load the one you marked as first view. So you are inflating the first layout R.layout.description_of_ads_expandable_list and reusing it for all the other lines in your list. The way you are checking for the type of child view to load is dangerous because it's incomplete . What do you think will happend if childPosition==1 && groupPosition==0 ? Booom! NullPointerException if your data source has one more element for the first group.

So first things first; you should fully implement HeterogeneousExpandableList interface if you want to use different layouts for different groups/children of your ExpandableListView.

Then using that interface work on the conditions of which layout should be loaded.

Finally work on the reuse view issue on public View getChildView(...).

Since am a nice guy here is a a snippet that should help you (based on the adapter you post) :

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;
    }
}

And this is how it looks like :

Hope this helps, let me know if it does/doesnt.