问题展开多层次ExpandableListView [英] Issue with Expanding Multi-Level ExpandableListView

查看:443
本文介绍了问题展开多层次ExpandableListView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多层次(3级,根 - >父 - >子)包含的孩子,也ExpandableListViews ExpandableListView。 我在填起来没有问题;但是,我要展开特定项目的父级的时候我第一次展示活动(的onCreate)。

我成功地扩大了家长的相关根系项目,但我似乎无法展开父项。给定的侦听器调用,但结果并没有反映在我的多级列表。

活动中,我所说的扩展:

 公共类活动{
    私人诠释groupToExpand = 4,childToExpand = 3;
    保护无效的onCreate(包savedInstance){
        最后ExpandableListView ELV =(ExpandableListView)findViewById(R.id.elv);
        如果(ArrayList的= NULL和放大器;!&安培;!arrayList.isEmpty()){
            elv.setAdapter(新RootAdapter(这一点,ArrayList的);
            //这个选择正确的组,但不扩大的孩子。
            elv.setSelectedChild(groupToExpand,childToExpand,真正的);
            elv.expandGroup(groupToExpand); //这个工程。
        }
    }
}
 

我的根适配器:

 公共类RootAdapter扩展BaseExpandableListAdapter {

私人列表<对象> ArrayList的;
私人上下文的背景下;
私人LayoutInflater充气;

公共RootAdapter(上下文的背景下,名单,其中,对象和GT;的ArrayList){
    this.context =背景;
    this.arrayList = ArrayList的;
    this.inflater = LayoutInflater.from(上下文);
}

@覆盖
公共对象getChild(INT groupPosition,诠释childPosition){
    最终对象的父=(对象)getGroup(groupPosition);
    返回parent.arrayList.get(childPosition);
}

@覆盖
众长getChildId(INT groupPosition,诠释childPosition){
    返回childPosition;
}

@覆盖
公共查看getChildView(INT groupPosition,INT childPosition,
        布尔isLastChild,查看convertView,ViewGroup中父){
    最终的对象O =(对象)getChild(groupPosition,childPosition);

    CustomExpandableListView ELV =(CustomExpandableListView)convertView;
    ChildViewHolder持有人;

    如果(ELV == NULL){
        持有人=新ChildViewHolder();

        ELV =新CustomExpandableListView(上下文);
        elv.setGroupIndicator(空);
        elv.setDivider(空);
        elv.setCacheColorHint(Color.parseColor(#00000000));
        elv.setChildDivider(空);
        elv.setChildIndicator(空);
        elv.setScrollingCacheEnabled(假);
        elv.setAnimationCacheEnabled(假);

        holder.cListView = ELV;
        elv.setTag(保持器);
    } 其他 {
        支架=(ChildViewHolder)elv.getTag();
    }

    最后ParentAdapter适配器=新ParentAdapter(背景下,O);
    holder.cListView.setAdapter(适配器);

    返回ELV;
}

私有静态类ChildViewHolder {
    CustomExpandableListView cListView;
}

@覆盖
公众诠释getChildrenCount(INT groupPosition){
    最终对象的父=(对象)getGroup(groupPosition);
    返回parent.arrayList.size();
}

@覆盖
公共对象getGroup(INT groupPosition){
    返回arrayList.get(groupPosition);
}

@覆盖
公众诠释getGroupCount(){
    返回arrayList.size();
}

@覆盖
众长getGroupId(INT groupPosition){
    返回groupPosition;
}

@覆盖
公共查看getGroupView(INT groupPosition,布尔isExpanded,
        查看convertView,ViewGroup中父){
    查看布局= convertView;
    GroupViewHolder持有人;
    最终的对象O =(对象)getGroup(groupPosition);

    如果(布局== NULL){
        布局= inflater.inflate(R.layout.item_to_inflate,父母,假);
        持有人=新GroupViewHolder();

        holder.title =(TextView中)layout.findViewById(R.id.title);
        holder.image =(ImageView的)layout.findViewById(R.id.image);
        layout.setTag(保持器);
    } 其他 {
        支架=(GroupViewHolder)layout.getTag();
    }

    holder.title.setText(o.title.trim());

    返回布局;
}

@覆盖
公共布尔hasStableIds(){
    返回true;
}

@覆盖
公共布尔isChildSelectable(INT groupPosition,诠释childPosition){
    返回true;
}

私有静态类GroupViewHolder {
    TextView的称号;
    ImageView的形象;
}

公共类CustomExpandableListView扩展ExpandableListView {

    公共CustomExpandableListView(上下文的背景下){
        超(上下文);
    }

    @覆盖
    保护无效onMeasure(INT widthMeasureSpec,诠释heightMeasureSpec){
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000,MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
    }

}

}
 

最后我ParentAdapter:

 公共类ParentAdapter扩展BaseExpandableListAdapter {

私有对象的孩子;
私人LayoutInflater充气;

公共ParentAdapter(上下文的背景下,对象子){
    this.child =子女;
    this.inflater = LayoutInflater.from(上下文);
}

@覆盖
公共对象getChild(INT groupPosition,诠释childPosition){
    返回child.arrayList.get(childPosition);
}

@覆盖
众长getChildId(INT groupPosition,诠释childPosition){
    返回childPosition;
}

@覆盖
公共查看getChildView(INT groupPosition,INT childPosition,
        布尔isLastChild,查看convertView,ViewGroup中父){
    查看布局= convertView;
    最终的对象O =(对象)getChild(0,childPosition);

    ChildViewHolder持有人;

    如果(布局== NULL){
        布局= inflater.inflate(R.layout.item_to_inflate,父母,假);

        持有人=新ChildViewHolder();
        holder.title =(TextView中)layout.findViewById(R.id.title);
        layout.setTag(保持器);
    } 其他 {
        支架=(ChildViewHolder)layout.getTag();
    }

    holder.title.setText(o.title.trim());

    返回布局;
}

@覆盖
公众诠释getChildrenCount(INT groupPosition){
    返回child.arrayList.size();
}

@覆盖
公共对象getGroup(INT groupPosition){
    返回的孩子;
}

@覆盖
公众诠释getGroupCount(){
    返回1;
}

@覆盖
众长getGroupId(INT groupPosition){
    返回groupPosition;
}

@覆盖
公共查看getGroupView(INT groupPosition,布尔isExpanded,
        查看convertView,ViewGroup中父){
    查看布局= convertView;
    GroupViewHolder持有人;

    如果(布局== NULL){
        布局= inflater.inflate(R.layout.item_to_inflate,父母,假);
        持有人=新GroupViewHolder();

        holder.image =(ImageView的)layout.findViewById(R.id.image);
        holder.title =(TextView中)layout.findViewById(R.id.title);
        layout.setTag(保持器);
    } 其他 {
        支架=(GroupViewHolder)layout.getTag();
    }
    holder.title.setText(o.title.trim());

    返回布局;
}

@覆盖
公共布尔hasStableIds(){
    返回true;
}

@覆盖
公共布尔isChildSelectable(INT groupPosition,诠释childPosition){
    返回true;
}

私有静态类GroupViewHolder {
    TextView的称号;
    ImageView的形象;
}

私有静态类ChildViewHolder {
    TextView的称号;
}

}
 

我不能展开根ExpandableListView中的子名单;你知道,扩大项目在父级别的任何正确的方法是什么?

我试图在RootAdapter的getChildView:

 如果(groupToExpand == groupPosition和放大器;&安培; childToExpand == childPosition){
    elv.expandGroup(childToExpand);
}
 

然后在我改变了活动:

 如果(ArrayList的= NULL和放大器;!&安培;!arrayList.isEmpty()){
    RootAdapter适配器=新RootAdapter(这一点,ArrayList的);
    elv.setAdapter(适配器);
    //这个选择正确的组,但不扩大的孩子。
    elv.setSelectedChild(groupToExpand,childToExpand,真正的);
    elv.expandGroup(groupToExpand); //这个工程。

    adapter.groupToExpand = groupToExpand;
    adapter.childToExpand = childToExpand;
    adapter.notifyDataSetChanged();
}
 

这扩展了父级别项目,但是,它所产生的家长重复的项目。我该如何正确地做到这一点?这是正确的方式,但我的适配器坏了,因此产生重复的项目?

我只是找不到我在这里缺少什么?

解决方案

我最终使用的计算器中的另一篇文章多层次ExpandableListView适配器

。不幸的是我只是找不到链接了,所以我就发表我的code在这里。

在ExpandableListView适配器的最高水平。

RootAdapter.java:

 公共类RootAdapter扩展BaseExpandableListAdapter {

    私人对象根;

    私人最终LayoutInflater充气;

    公共类条目{
        公众最终CustExpListview CLS;
        公众最终SecondLevelAdapter sadpt;

        公共入口(CustExpListview CLS,SecondLevelAdapter sadpt){
            this.cls = CLS;
            this.sadpt = sadpt;
        }
    }

    公共入口[lsfirst]

    //你可以改变的构造取决于你wan't要使用的监听器上。
    公共RootAdapter(上下文的背景下,对象根,ExpandableListView.OnGroupClickListener grpLst,
        ExpandableListView.OnChildClickListener childLst,ExpandableListView.OnGroupExpandListener grpExpLst){
        this.root =根;
        this.inflater = LayoutInflater.from(上下文);

        lsfirst =新条目[root.children.size()];

        的for(int i = 0; I< root.children.size();我++){
            最后CustExpListview celv​​ =新CustExpListview(上下文);
            SecondLevelAdapter ADP =新SecondLevelAdapter(root.children.get(一));
            celv.setAdapter(ADP);
            celv.setGroupIndicator(空);
            celv.setOnChildClickListener(childLst);
            celv.setOnGroupClickListener(grpLst);
            celv.setOnGroupExpandListener(grpExpLst);

            lsfirst [我] =新条目(celv,ADP);
        }

    }

    @覆盖
    公共对象getChild(INT groupPosition,诠释childPosition){
        返回childPosition;
    }

    @覆盖
    众长getChildId(INT groupPosition,诠释childPosition){
        返回childPosition;
    }

    @覆盖
    公共查看getChildView(INT groupPosition,诠释childPosition,布尔isLastChild,
        查看convertView,ViewGroup中父){
        //第二级列表
        返回lsfirst [groupPosition] .CLS;
    }

    @覆盖
    公众诠释getChildrenCount(INT groupPosition){
        返回1;
    }

    @覆盖
    公共对象getGroup(INT groupPosition){
        返回root.children.get(groupPosition);
    }

    @覆盖
    公众诠释getGroupCount(){
        返回root.children.size();
    }

    @覆盖
    众长getGroupId(INT groupPosition){
        返回groupPosition;
    }

    @覆盖
    公共查看getGroupView(INT groupPosition,布尔isExpanded,查看convertView,
        ViewGroup中父){

        //第一级

        查看布局= convertView;
        GroupViewHolder持有人;
        最终目标项=(对象)getGroup(groupPosition);

        如果(布局== NULL){
            布局= inflater.inflate(R.layout.item_root,父母,假);
            持有人=新GroupViewHolder();
            holder.title =(TextView中)layout.findViewById(R.id.itemRootTitle);
            layout.setTag(保持器);
        } 其他 {
            支架=(GroupViewHolder)layout.getTag();
        }

        holder.title.setText(item.title.trim());

        返回布局;
    }

    私有静态类GroupViewHolder {
        TextView的称号;
    }

    @覆盖
    公共布尔hasStableIds(){
        返回true;
    }

    @覆盖
    公共布尔isChildSelectable(INT groupPosition,诠释childPosition){
        返回true;
    }
}
 

定制ExpandableListView与溶液项有时不被显示。还有一个解决办法,为抛出:IllegalArgumentException一个已知的bug破坏视图时被调用(由pressing后退按钮本质上)。

CustExpListview.java:

 公共类CustExpListview扩展ExpandableListView {

    公共CustExpListview(上下文的背景下){
        超(上下文);

    }

    保护无效onMeasure(INT widthMeasureSpec,诠释heightMeasureSpec){
        //值(2000)不应该是固定的,计算
        //如下:cell_height x root_items_count x root_items_children_count
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000,MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
    }

    @覆盖
    保护无效onDetachedFromWindow(){
        尝试 {
            super.onDetachedFromWindow();
        }赶上(抛出:IllegalArgumentException E){
            // TODO:解决方法对于http://$c$c.google.com/p/android/issues/detail ID = 22751
        }
    }
}
 

最后,code到末级适配器。

 公共类SecondLevelAdapter扩展BaseExpandableListAdapter {

    公共对象的孩子;

    公共SecondLevelAdapter(对象子){
        this.child =子女;
    }

    @覆盖
    公共对象getChild(INT groupPosition,诠释childPosition){
        返回child.children.get(groupPosition).children.get(childPosition);
    }

    @覆盖
    众长getChildId(INT groupPosition,诠释childPosition){
        返回childPosition;
    }

    //第三个层次
    @覆盖
    公共查看getChildView(INT groupPosition,诠释childPosition,布尔isLastChild,
            查看convertView,ViewGroup中父){
        查看布局= convertView;
        最终目标项=(对象)getChild(groupPosition,childPosition);

        ChildViewHolder持有人;

        如果(布局== NULL){
            布局= inflater.inflate(R.layout.item_child,父母,假);

            持有人=新ChildViewHolder();
            holder.title =(TextView中)layout.findViewById(R.id.itemChildTitle);
            layout.setTag(保持器);
        } 其他 {
            支架=(ChildViewHolder)layout.getTag();
        }

        holder.title.setText(item.title.trim());

        返回布局;
    }

    @覆盖
    公众诠释getChildrenCount(INT groupPosition){
        返回child.children.get(groupPosition).children.size();
    }

    @覆盖
    公共对象getGroup(INT groupPosition){
        返回child.children.get(groupPosition);
    }

    @覆盖
    公众诠释getGroupCount(){
        返回child.children.size();
    }

    @覆盖
    众长getGroupId(INT groupPosition){
        返回groupPosition;
    }

    //第二级
    @覆盖
    公共查看getGroupView(INT groupPosition,布尔isExpanded,查看convertView,
            ViewGroup中父){
        查看布局= convertView;
        ViewHolder持有人;

        最终目标项=(对象)getGroup(groupPosition);

        如果(布局== NULL){
            布局= inflater.inflate(R.layout.item_parent,父母,假);
            持有人=新ViewHolder();
            holder.title =(TextView中)layout.findViewById(R.id.itemParentTitle);
            layout.setTag(保持器);
        } 其他 {
            支架=(ViewHolder)layout.getTag();
        }

        holder.title.setText(item.title.trim());

        返回布局;
    }

    @覆盖
    公共无效registerDataSetObserver(DataSetObserver观察者){
        super.registerDataSetObserver(观察员);
    }

    @覆盖
    公共无效unregisterDataSetObserver(DataSetObserver观察者){
        Log.d(SecondLevelAdapter,注销观察者);
        如果(观察者!= NULL){
            super.unregisterDataSetObserver(观察员);
        }
    }

    @覆盖
    公共布尔hasStableIds(){
        返回true;
    }

    @覆盖
    公共布尔isChildSelectable(INT groupPosition,诠释childPosition){
        返回true;
    }

    私有静态类ViewHolder {
        TextView的称号;
    }

    私有静态类ChildViewHolder {
        TextView的称号;
    }

}
 

我希望这有助于!

更新

这是我如何调用上面的适配器的例子。

MainActivity:

  @覆盖
保护无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);

    最后的名单,其中,对象>对象= yourItems;
    如果(!objects.isEmpty()){
        最后ExpandableListView ELV =(ExpandableListView)findViewById(R.id.yourExpandableListView);
        / * *以下项目点击监听器/

        在ExpandableListView //第一级项目
        elv.setOnGroupClickListener(新ExpandableListView.OnGroupClickListener(){
            @覆盖
            公共布尔onGroupClick(ExpandableListView eListView,视图中查看,INT groupPosition,
                    长ID){
                // TODO:你需要什么
                返回false / *或真正取决于你所需要的* /;
            }
        });

        在ExpandableListView //第二级项目
        ExpandableListView.OnGroupClickListener grpLst =新ExpandableListView.OnGroupClickListener(){
            @覆盖
            公共布尔onGroupClick(ExpandableListView eListView,视图中查看,INT groupPosition,
                    长ID){
                // TODO:你需要什么
                返回false / *或真正取决于你所需要的* /;
            }
        };

        //第三个(也是最后一次)的ExpandableListView级别的项目
        ExpandableListView.OnChildClickListener childLst =新ExpandableListView.OnChildClickListener(){
            @覆盖
            公共布尔onChildClick(ExpandableListView eListView,视图中查看,INT groupPosition,
                    INT childPosition,长ID){
                // TODO:你需要什么
                返回false / *或真正取决于你所需要的* /;
            }
        };

        ExpandableListView.OnGroupExpandListener grpExpLst =新ExpandableListView.OnGroupExpandListener(){
            @覆盖
            公共无效onGroupExpand(INT groupPosition){
                / *这个人是不是必需的,当然,你可以从RootAdapter构造函数删除
                 *这只是一个例子,如何实现第二个层次的项目听众* /
            }
        };

        最后RootAdapter适配器=新RootAdapter(这一点,对象,grpLst,childLst,grpExpLst);
        elv.setAdapter(适配器);
    }
}
 

这是我的类对象将是什么样子。

Object.java:

 公共类对象{
    公共字符串称号; //使用getter和setter方法​​,而不是
    公开名单<对象>儿童; //与上述相同的

    公共对象(){
        孩子=新的ArrayList<对象>();
    }
}
 

I have a multi level (3 levels, Root -> Parent -> Child) ExpandableListView containing children that are also ExpandableListViews. I'm having no issue filling them up; however, I need to expand a specific item in the Parent level when I first display the Activity (onCreate).

I successfully expand the related Root item of the Parent but I can't seem to expand the Parent item. The given listeners are called and yet the result isn't reflected in my multi level list.

Activity in which I call the expansion:

public class Activity {
    private int groupToExpand = 4, childToExpand = 3;
    protected void onCreate(Bundle savedInstance) {
        final ExpandableListView elv = (ExpandableListView) findViewById(R.id.elv);
        if (arrayList!= null && !arrayList.isEmpty()) {
            elv.setAdapter(new RootAdapter(this, arrayList);
            // this selects the correct group, but doesn't expand the child.
            elv.setSelectedChild(groupToExpand, childToExpand, true); 
            elv.expandGroup(groupToExpand); // this works.
        }
    }
}

My Root adapter:

public class RootAdapter extends BaseExpandableListAdapter {

private List<Objects> arrayList;
private Context context;
private LayoutInflater inflater;

public RootAdapter(Context context, List<Objects> arrayList) {
    this.context = context;
    this.arrayList = arrayList;
    this.inflater = LayoutInflater.from(context);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    final Objects parent = (Objects) getGroup(groupPosition);
    return parent.arrayList.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) {
    final Objects o = (Objects) getChild(groupPosition, childPosition);

    CustomExpandableListView elv = (CustomExpandableListView) convertView;
    ChildViewHolder holder;

    if (elv == null) {
        holder = new ChildViewHolder();

        elv = new CustomExpandableListView(context);
        elv.setGroupIndicator(null);
        elv.setDivider(null);
        elv.setCacheColorHint(Color.parseColor("#00000000"));
        elv.setChildDivider(null);
        elv.setChildIndicator(null);
        elv.setScrollingCacheEnabled(false);
        elv.setAnimationCacheEnabled(false);

        holder.cListView = elv;
        elv.setTag(holder);
    } else {
        holder = (ChildViewHolder) elv.getTag();
    }

    final ParentAdapter adapter = new ParentAdapter(context, o);
    holder.cListView.setAdapter(adapter);

    return elv;
}

private static class ChildViewHolder {
    CustomExpandableListView cListView;
}

@Override
public int getChildrenCount(int groupPosition) {
    final Objects parent = (Objects) getGroup(groupPosition);
    return parent.arrayList.size();
}

@Override
public Object getGroup(int groupPosition) {
    return arrayList.get(groupPosition);
}

@Override
public int getGroupCount() {
    return arrayList.size();
}

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
        View convertView, ViewGroup parent) {
    View layout = convertView;
    GroupViewHolder holder;
    final Objects o = (Objects) getGroup(groupPosition);

    if (layout == null) {
        layout = inflater.inflate(R.layout.item_to_inflate, parent, false);
        holder = new GroupViewHolder();

        holder.title = (TextView) layout.findViewById(R.id.title);
        holder.image = (ImageView) layout.findViewById(R.id.image);
        layout.setTag(holder);
    } else {
        holder = (GroupViewHolder) layout.getTag();
    }

    holder.title.setText(o.title.trim());

    return layout;
}

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return true;
}

private static class GroupViewHolder {
    TextView title;
    ImageView image;
}

public class CustomExpandableListView extends ExpandableListView {

    public CustomExpandableListView(Context context) {
        super(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

}

}

Finally my ParentAdapter :

public class ParentAdapter extends BaseExpandableListAdapter {

private Objects child;
private LayoutInflater inflater;

public ParentAdapter(Context context, Objects child) {
    this.child = child;
    this.inflater = LayoutInflater.from(context);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    return child.arrayList.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) {
    View layout = convertView;
    final Objects o = (Objects) getChild(0, childPosition);

    ChildViewHolder holder;

    if (layout == null) {
        layout = inflater.inflate(R.layout.item_to_inflate, parent, false);

        holder = new ChildViewHolder();
        holder.title = (TextView) layout.findViewById(R.id.title);
        layout.setTag(holder);
    } else {
        holder = (ChildViewHolder) layout.getTag();
    }

    holder.title.setText(o.title.trim());

    return layout;
}

@Override
public int getChildrenCount(int groupPosition) {
    return child.arrayList.size();
}

@Override
public Object getGroup(int groupPosition) {
    return child;
}

@Override
public int getGroupCount() {
    return 1;
}

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
        View convertView, ViewGroup parent) {
    View layout = convertView;
    GroupViewHolder holder;

    if (layout == null) {
        layout = inflater.inflate(R.layout.item_to_inflate, parent, false);
        holder = new GroupViewHolder();

        holder.image = (ImageView) layout.findViewById(R.id.image);
        holder.title = (TextView) layout.findViewById(R.id.title);
        layout.setTag(holder);  
    } else {
        holder = (GroupViewHolder) layout.getTag();
    }
    holder.title.setText(o.title.trim());

    return layout;
}

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return true;
}

private static class GroupViewHolder {
    TextView title;
    ImageView image;
}

private static class ChildViewHolder {
    TextView title;
}

}

I can't expand the child lists within the root ExpandableListView; do you know any correct way to expand the items at the Parent level?

I tried in getChildView of the RootAdapter :

if (groupToExpand == groupPosition && childToExpand == childPosition) {
    elv.expandGroup(childToExpand);
}

Then in the activity i changed:

if (arrayList!= null && !arrayList.isEmpty()) {
    RootAdapter adapter = new RootAdapter(this, arrayList);
    elv.setAdapter(adapter);
    // this selects the correct group, but doesn't expand the child.
    elv.setSelectedChild(groupToExpand, childToExpand, true); 
    elv.expandGroup(groupToExpand); // this works.

    adapter.groupToExpand = groupToExpand;
    adapter.childToExpand = childToExpand;
    adapter.notifyDataSetChanged();
}

This expands the Parent level item, BUT, it generates duplicate items of the Parent. How do I do this correctly? Is this the correct way but my adapter is broken, therefore generating duplicate items?

I just can't find what I'm missing here...

解决方案

I ended up using a multi level ExpandableListView adapter from another post in stackoverflow. Unfortunately I just can't find the link anymore so I'll just post my code here.

Top Level of the ExpandableListView adapter.

RootAdapter.java:

public class RootAdapter extends BaseExpandableListAdapter {

    private Object root;

    private final LayoutInflater inflater;

    public class Entry {
        public final CustExpListview cls;
        public final SecondLevelAdapter sadpt;

        public Entry(CustExpListview cls, SecondLevelAdapter sadpt) {
            this.cls = cls;
            this.sadpt = sadpt;
        }
    }

    public Entry[] lsfirst;

    // you can change the constructor depending on which listeners you wan't to use.
    public RootAdapter(Context context, Object root, ExpandableListView.OnGroupClickListener grpLst,
        ExpandableListView.OnChildClickListener childLst, ExpandableListView.OnGroupExpandListener grpExpLst) {
        this.root = root;
        this.inflater = LayoutInflater.from(context);

        lsfirst = new Entry[root.children.size()];

        for (int i = 0; i < root.children.size(); i++) {
            final CustExpListview celv = new CustExpListview(context);
            SecondLevelAdapter adp = new SecondLevelAdapter(root.children.get(i));
            celv.setAdapter(adp);
            celv.setGroupIndicator(null);
            celv.setOnChildClickListener(childLst);
            celv.setOnGroupClickListener(grpLst);
            celv.setOnGroupExpandListener(grpExpLst);

            lsfirst[i] = new Entry(celv, adp);
        }

    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return 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) {
        // second level list
        return lsfirst[groupPosition].cls;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return 1;
    }

    @Override
    public Object getGroup(int groupPosition) {
        return root.children.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        return root.children.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
        ViewGroup parent) {

        // first level

        View layout = convertView;
        GroupViewHolder holder;
        final Object item = (Object) getGroup(groupPosition);

        if (layout == null) {
            layout = inflater.inflate(R.layout.item_root, parent, false);
            holder = new GroupViewHolder();
            holder.title = (TextView) layout.findViewById(R.id.itemRootTitle);
            layout.setTag(holder);
        } else {
            holder = (GroupViewHolder) layout.getTag();
        }

        holder.title.setText(item.title.trim());

        return layout;
    }

    private static class GroupViewHolder {
        TextView title;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
}

Custom ExpandableListView with the solution to items sometimes not being displayed. There is also a workaround to a known bug for IllegalArgumentException being called when destroying the view (by pressing the back button essentially).

CustExpListview.java:

public class CustExpListview extends ExpandableListView {

    public CustExpListview(Context context) {
        super(context);

    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // the value (2000) should not be fixed and be calculated
        // as follows: cell_height x root_items_count x root_items_children_count
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(2000, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDetachedFromWindow() {
        try {
            super.onDetachedFromWindow();
        } catch (IllegalArgumentException e) {
            // TODO: Workaround for http://code.google.com/p/android/issues/detail?id=22751
        }
    }
}

Finally, the code to the last level adapter.

public class SecondLevelAdapter extends BaseExpandableListAdapter {

    public Object child;

    public SecondLevelAdapter(Object child) {
        this.child = child;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return child.children.get(groupPosition).children.get(childPosition);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    // third level
    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
            View convertView, ViewGroup parent) {
        View layout = convertView;
        final Object item = (Object) getChild(groupPosition, childPosition);

        ChildViewHolder holder;

        if (layout == null) {
            layout = inflater.inflate(R.layout.item_child, parent, false);

            holder = new ChildViewHolder();
            holder.title = (TextView) layout.findViewById(R.id.itemChildTitle);
            layout.setTag(holder);
        } else {
            holder = (ChildViewHolder) layout.getTag();
        }

        holder.title.setText(item.title.trim());

        return layout;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return child.children.get(groupPosition).children.size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return child.children.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        return child.children.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    // Second level
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
            ViewGroup parent) {
        View layout = convertView;
        ViewHolder holder;

        final Object item = (Object) getGroup(groupPosition);

        if (layout == null) {
            layout = inflater.inflate(R.layout.item_parent, parent, false);
            holder = new ViewHolder();
            holder.title = (TextView) layout.findViewById(R.id.itemParentTitle);
            layout.setTag(holder);
        } else {
            holder = (ViewHolder) layout.getTag();
        }

        holder.title.setText(item.title.trim());

        return layout;
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        super.registerDataSetObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        Log.d("SecondLevelAdapter", "Unregistering observer");
        if (observer != null) {
            super.unregisterDataSetObserver(observer);
        }
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

    private static class ViewHolder {
        TextView title;
    }

    private static class ChildViewHolder {
        TextView title;
    }

}

I hope this helps!!!

Update

This is an example of how I call the above adapter.

MainActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final List<Object> objects = yourItems;
    if (!objects.isEmpty()) {
        final ExpandableListView elv = (ExpandableListView) findViewById(R.id.yourExpandableListView);
        /* Item click listeners below */

        // First level items in the ExpandableListView
        elv.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView eListView, View view, int groupPosition,
                    long id) {
                // TODO: whatever you need
                return false /* or true depending on what you need */;
            }
        });

        // Second level items in the ExpandableListView
        ExpandableListView.OnGroupClickListener grpLst = new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView eListView, View view, int groupPosition,
                    long id) {
                // TODO: whatever you need
                return false /* or true depending on what you need */;
            }
        };

        // Third (and last) level items in the ExpandableListView
        ExpandableListView.OnChildClickListener childLst = new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView eListView, View view, int groupPosition,
                    int childPosition, long id) {
                // TODO: whatever you need
                return false /* or true depending on what you need */;
            }
        };

        ExpandableListView.OnGroupExpandListener grpExpLst = new ExpandableListView.OnGroupExpandListener() {
            @Override
            public void onGroupExpand(int groupPosition) {
                /* this one is not required of course, you can delete it from the RootAdapter Constructor
                 * it is just an example as to how to implement Listeners on the second level items */
            }
        };

        final RootAdapter adapter = new RootAdapter(this, objects, grpLst, childLst, grpExpLst);
        elv.setAdapter(adapter);
    }
}

This is how my class Object would look like.

Object.java:

public class Object {
    public String title; // use getters and setters instead
    public List<Object> children; // same as above

    public Object() {
        children = new ArrayList<Object>();
    }
}

这篇关于问题展开多层次ExpandableListView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆