【问题标题】:Expandable listview with selectall checkbox : group itemclick and scrolling bug带有全选复选框的可扩展列表视图:组项目单击和滚动错误
【发布时间】:2012-11-17 16:57:19
【问题描述】:

我有一个 ExpandableListView,组名旁边有一个复选框,展开时,子项也有复选框。

假设我有 4 个小组,有 50 个孩子。当一个组展开时,我单击全选复选框,一切正常,所有复选框都被选中并在我滚动时保持它们的状态。

但是,如果我滚动到列表的最后一个子项,之后滚动就会出错(滚动到顶部然后触摸屏幕以停止滚动不再起作用),单击组也不再起作用,直到我再次单击全选复选框。 点击一个子复选框没有任何作用,我必须点击全选复选框才能正常工作。

我更改了子复选框、组复选框的可聚焦状态并尝试了很多方法,但我找不到解决方案。你知道它的来源吗?

public class ExpandableListAdapter extends BaseExpandableListAdapter {


    LayoutInflater cinflater;
    LayoutInflater ginflater;
    ArrayList<Group> array;
    Context context;


    public ExpandableListAdapter(Context context, ArrayList<Group> array) {
        super();

        cinflater = LayoutInflater.from(context);
        ginflater = LayoutInflater.from(context);

        this.array = array;
        this.context = context;

    }


    public class ChildViewHolder {

        CheckBox contactcheckbox;
        TextView name;

    }


    @Override
    public int getChildrenCount(int groupPosition) {
        // TODO Auto-generated method stub
        return array.get(groupPosition).getContacts().size();
    }


    private OnCheckedChangeListener contactchecklistener = new OnCheckedChangeListener() {
               @Override
               public void onCheckedChanged(CompoundButton checkboxView, boolean isChecked) {

                   Contact contact = (Contact) checkboxView.getTag();
                   contact.setCheck(isChecked);

               }

            };

    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {

        ChildViewHolder cholder;

        if(convertView == null){

            cholder = new ChildViewHolder();

            convertView = cinflater.inflate(R.layout.childsitems, null);

            cholder.name = (TextView) convertView.findViewById(R.id.childnametextview);

            cholder.contactcheckbox = (CheckBox) convertView.findViewById(R.id.childcheckbox);
            cholder.contactcheckbox.setOnCheckedChangeListener(contactchecklistener);


            convertView.setTag(cholder);

        }else{

            cholder = (ChildViewHolder) convertView.getTag();

        }

        cholder.contactcheckbox.setTag(array.get(groupPosition).getContacts().get(childPosition));
        cholder.contactcheckbox.setChecked(array.get(groupPosition).getContacts().get(childPosition).isCheck());

        cholder.name.setText(array.get(groupPosition).getContacts().get(childPosition).getName());

        return convertView;
    }



    public class GroupViewHolder {
        TextView groupname;
        CheckBox groupcheck;

    }


    @Override
    public int getGroupCount() {
        // TODO Auto-generated method stub
        return array.size();
    }

    private OnCheckedChangeListener groupchecklistener = new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            int index = (Integer) buttonView.getTag();

            for(int i = 0;i<array.get(index).getContacts().size();i++){
                array.get(index).getContacts().get(i).setCheck(isChecked);
            }

            array.get(index).setCheck(isChecked);

            notifyDataSetChanged();

        }
    };


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


        GroupViewHolder gholder;

        if(convertView==null){
            gholder =  new GroupViewHolder();
            convertView = ginflater.inflate(R.layout.groupsitems,null);

            gholder.groupname = (TextView)convertView.findViewById(R.id.groupnametextview);
            gholder.groupcheckbox = (CheckBox)convertView.findViewById(R.id.groupcheckbox);
            gholder.groupcheckbox.setOnCheckedChangeListener(groupchecklistener);

            convertView.setTag(gholder);

        }else{
            gholder = (GroupViewHolder)convertView.getTag();
        }

        gholder.groupname.setText(array.get(groupPosition).getGroupname());
        gholder.groupname.setTextSize(24);
        gholder.groupname.setTextColor(Color.parseColor("#FF858585"));
        gholder.groupname.setTypeface(Typeface.DEFAULT, Typeface.BOLD);

        int paddingleft = 48;  // 38 dps
        final float scale = getResources().getDisplayMetrics().density;
        int dpvalue = (int) (paddingleft * scale + 0.5f);
        gholder.groupname.setPadding(dpvalue, 16, 0, 16);


        gholder.groupcheckbox.setTag(groupPosition);
        gholder.groupcheckbox.setChecked(array.get(groupPosition).isCheck());

        if(isExpanded == true){
                  convertView.setBackgroundDrawable(getResources().getDrawable(R.drawable.expandedbackground));
        }else{
            convertView.setBackgroundColor(Color.TRANSPARENT);
        }

        return convertView;
    }





    @Override
    public Object getChild(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Object getGroup(int groupPosition) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getGroupId(int groupPosition) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public boolean hasStableIds() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        // TODO Auto-generated method stub
        return false;
    }

}

groupsitems.xml:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >


    <CheckBox
        android:id="@+id/groupcheckbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="12dp"
        android:focusable="false"
        android:gravity="right|center"
        android:paddingRight="10dp" />

<TextView
android:id="@+id/groupnametextview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@+id/groupcheckbox"
android:focusableInTouchMode="false"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FF858585"
android:textStyle="bold" />

</RelativeLayout>

childitems.xml:

<RelativeLayout
    android:id="@+id/relativeLayout1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:layout_marginTop="8dp"
    android:paddingLeft="8dp" >


<TextView
        android:id="@+id/childnametextview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/childcheckbox"
        android:gravity="right|center"
        android:paddingLeft="16dp"
        android:textColor="#FFAFAFAF"
        android:textSize="16sp"
        android:textStyle="bold" />

<CheckBox
        android:id="@+id/childcheckbox"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

【问题讨论】:

  • @ADR 您从哪里读到“单击最后一项会引发错误”?我看不到任何关于抛出异常的信息...此编辑不正确。
  • 贴出您的相关代码,否则我们可能无法为您提供帮助。
  • 是的,没有错误什么的,我从来没有说过点击最后一项...我没有发布代码以保持简单,但它就是这样。
  • 能否请您发布整个源代码。我必须实现类似的东西,但我被卡住了!

标签: android android-layout


【解决方案1】:

我找到了解决方案。我没有在 groupcheckbox 上使用 OnCheckedChangeListener,而是使用了 OnClickListener,它解决了这样的所有问题:

gholder.groupcheckbox.setChecked(array.get(groupPosition).isCheck());
gholder.groupcheckbox.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                for(int i = 0;i<array.get(groupPosition).getContacts().size();i++){
                    array.get(groupPosition).getContacts().get(i).setCheck(gholder.groupcheckbox.isChecked());
                }

                array.get(groupPosition).setCheck(gholder.groupcheck.isChecked());

                notifyDataSetChanged();
            }
        });

【讨论】:

  • 大声笑,就像我在写答案一样,你刚刚击败了我。这是我之前遇到的一个烦人的问题。基本上正在发生的事情是您的列表视图被锁定,因为它被notifyDataSetChanged(); 称为很多,太多了。当您滚动并看到新的复选框时,您的方法正在纠正复选框以显示它们是否被选中。然后调用 onCheckedChanged。这是一个必要的困境,因为您正确使用了viewHolder 模式并检查了空convertview。正如你所做的那样,我认为将其设置为 onClick 是正确的。
  • 感谢您的帮助。如此简单却又如此难找。
猜你喜欢
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多