在ExpandableListView上滚动时,Select复选框重复 [英] Select checkbox is duplicated when scrolling on an ExpandableListView

查看:58
本文介绍了在ExpandableListView上滚动时,Select复选框重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个BaseExpandableListAdapter(下面的代码),它可以操纵ExpandableListView和一个称为Checklist的模型.

I have a BaseExpandableListAdapter (code below) wich manipulates an ExpandableListView and a model called Checklist.

清单模型包含类别列表. 类别是检查清单. 支票是低点列表. 低"包含一个布尔项,在视图中由一个复选框表示.

The Checklist model contains a List of Categories. A Category is a List of Checks. A Check is a List of Lows. And a Low contains a boolean item wich is represented by a checkbox in the view.

我使用ViewHolder模式来处理我的模型:GroupView使用CategoryViewHolder,ChildView使用CheckViewHolder.

I use a ViewHolder pattern to handle my models : CategoryViewHolder for my GroupView and CheckViewHolder for my ChildView.

我遇到的问题在getChildView方法中,当我在低"(选中)内选择一个复选框并向下滚动时,我发现另一个选中的复选框. 当我在Check内的edittext对象中写入内容并滚动时,会发生同样的情况.

The problem I have, is within the getChildView method, when I select a checkbox in a Low (within a Check) and scroll down, I find an other checkbox selected. The same thing happen when I write something in an edittext object within the Check and I scroll, an other edittext is edited.

我怀疑我的Vue回收工作不正常,但是我没有找到任何解决方案.

I suspect my vue recycling is not working properly but I haven’t found any solutions.

有什么想法吗?

public class ChecklistAdapter extends BaseExpandableListAdapter {
private Context mContext;
private Checklist mChecklist;
private boolean isEditable;
private final int ID_LOW_ADDED = -1;


public ChecklistAdapter(Context mContext, Checklist mChecklist, boolean editable) {
    this.mContext = mContext;
    this.mChecklist = mChecklist;
    this.isEditable = editable;
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    return mChecklist.getCategories().get(groupPosition).getChecks().get(childPosition);
}


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

// ChildView is the Check item with a label and buttons actions
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, final ViewGroup parent) {
    final CheckViewHolder holder;

    final List<Category> mCategories = mChecklist.getCategories();
    final Category mCategory = (Category) getGroup(groupPosition);
    final List<Check> mChecks = mCategory.getChecks();
    final Check mCheck = (Check) getChild(groupPosition, childPosition);
    final List<Low> mLows = mCheck.getLows();


    if (convertView != null){
        holder = (CheckViewHolder) convertView.getTag();
    }
    else {
        LayoutInflater inflater = (LayoutInflater) this.mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.item_check, parent, false);
        holder = new CheckViewHolder(convertView);
        convertView.setTag(holder);
    }

    Utils.logK("Holder = "+holder);

    // Prepare checking lows elements
    addLowsToView(mLows, convertView, holder);


    // Set Checks elements
    String label = mCheck.getLabel();
    holder.tvCheckLabel.setText(label);

    // Check the state of button
    final View finalConvertView = convertView;
    final ViewGroup finalParent = parent;
    holder.rgActions.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup radioGroup, @IdRes int rbId) {

            switch (rbId){
                case R.id.rb_ko:
                    holder.llLow.setVisibility(View.VISIBLE);
                    mCheck.setState(Check.KO);

                    //finalParent.scrollTo(0,finalConvertView.getTop());

                    //((ExpandableListView) parent).smoothScrollToPosition(finalConvertView.getTop());
                    //((ExpandableListView) parent).setSelection(0);
                    //Utils.logK("Scroll to top = "+finalConvertView.getTop());
                    break;
                case R.id.rb_nc:
                    holder.llLow.setVisibility(View.GONE);
                    mCheck.setState(Check.NC);
                    break;
                case R.id.rb_ok:
                    holder.llLow.setVisibility(View.GONE);
                    mCheck.setState(Check.OK);
                    break;
                default:
                    //TODO
            }

            // Prepere updated checklist object to send
            mChecks.set(childPosition, mCheck);
            mCategory.setChecks(mChecks);
            mCategories.set(groupPosition, mCategory);
            mChecklist.setCategories(mCategories);

        }
    });

    /**
     * Save the state of radioButtons (selection)
     */
    if(mCheck.getState() != null) {
        switch (mCheck.getState()) {
            case Check.KO:
                holder.rbKo.setChecked(true);
                holder.rbKo.setSelected(true);
                break;
            case Check.NC:
                holder.rbNc.setChecked(true);
                holder.rbNc.setSelected(true);
                break;
            case Check.OK:
                holder.rbOk.setChecked(true);
                holder.rbOk.setSelected(true);
                break;
        }
    }

    holder.cbOther.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

        int lowsSize = mLows.size();
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
            if (isChecked){
                holder.etOther.setEnabled(true);
            }
            else{
                holder.etOther.setEnabled(false);
            }

            // Add the new low and updated checklist object to send
            final Low mOtherLow = new Low();
            mOtherLow.setId(ID_LOW_ADDED);
            mOtherLow.setSelected(true);


            // TODO save checklist when text is added
            holder.etOther.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                }

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                }

                @Override
                public void afterTextChanged(Editable editable) {
                    mOtherLow.setLabel(holder.etOther.getText().toString());

                }
            });

            Utils.logK("otherLow added = "+mOtherLow.getLabel());

               //long idLastLowAdded = mLows.get(mLows.size()-1).getId();
                Utils.logK("Low added = "+mOtherLow.getLabel());
                mLows.add(mOtherLow);
                mCheck.setLows(mLows);
                mChecks.set(childPosition, mCheck);
                mCategory.setChecks(mChecks);
                mCategories.set(groupPosition, mCategory);
                mChecklist.setCategories(mCategories);


        }


    });

    holder.setViewsEnabled(isEditable);


    return convertView;
}

@Override
public int getChildrenCount(int groupPosition) {
    return mChecklist.getCategories().get(groupPosition).getChecks().size();
}

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


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

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


@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    final CategoryViewHolder groupHolder;
    final Category mCategory = (Category) getGroup(groupPosition);


    if (convertView != null){
        groupHolder = (CategoryViewHolder) convertView.getTag();
    }
    else {
        LayoutInflater inflater = (LayoutInflater) this.mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.item_category, parent, false);
        groupHolder = new CategoryViewHolder(convertView);

        convertView.setTag(groupHolder);
    }

    groupHolder.tvCategoryTitle.setText(mCategory.getLabel());

    return convertView;
}


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

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


/**
 * Add the lines of works to my check item (checkboxes)
 * @param lows List of line of work
 * @param v The view will be attached this new view
 */
private void addLowsToView(final List<Low> lows, View v, final CheckViewHolder holder) {
    LinearLayout llLowPosition = v.findViewById(R.id.ll_low_position);
    if(((LinearLayout) llLowPosition).getChildCount() > 0)
        ((LinearLayout) llLowPosition).removeAllViews();

    for (int i = 0; i < lows.size(); i++) {

        final int position = i;
        final Low low = lows.get(i);
        // Ignore the "others" lows (id of an other low start at -1 and decrement for each time the
        // user click on "other" checkbox
        if (low.getId()<0){
            if (isEditable){
                break;
            }
            else{
                holder.cbOther.setSelected(true);
                holder.etOther.setText(low.getLabel());
            }
        }
        else {

            CheckBox cbLow = new CheckBox(mContext);
            cbLow.setText(lows.get(i).getLabel());
            cbLow.setChecked(lows.get(i).isSelected());
            //cbLow.setButtonDrawable(ContextCompat.getColor(mContext,R.color.accent));
            cbLow.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                    low.setSelected(isChecked);
                    lows.set(position, low);
                }
            });
            llLowPosition.addView(cbLow, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            // Disable if it's not editable mode
            if (!isEditable){
                cbLow.setEnabled(false);
            }
        }



    }

}

/**
 * Allow activity to get the updated checklist
 * @return The updated checklist
 */
public Checklist getChecklist(){
    return mChecklist;
}


/**
 * Class that define the view holder of a child : the check model
 */
static class CheckViewHolder{
    @BindView(R.id.tv_check_label)
    TextView tvCheckLabel;

    @BindView(R.id.rg_actions)
    RadioGroup rgActions;

    @BindView(R.id.ll_low)
    LinearLayout llLow;

    @BindView(R.id.ll_low_position)
    LinearLayout llLowPosition;

    @BindView(R.id.cb_other)
    CheckBox cbOther;

    @BindView(R.id.et_other)
    EditText etOther;

    @BindView(R.id.rb_ko)
    RadioButton rbKo;

    @BindView(R.id.rb_nc)
    RadioButton rbNc;

    @BindView(R.id.rb_ok)
    RadioButton rbOk;

    @BindView(R.id.cv_item_check)
    CardView cvItemCheck;


    public CheckViewHolder(View view){
        ButterKnife.bind(this, view);
    }

    /**
     * Set actions on the view. If it's not editable, disable all actions.
     * @param editable : Mode of view : consulting or editing
     */
    public void setViewsEnabled(boolean editable){
        rgActions.setEnabled(editable);
        llLowPosition.setEnabled(editable);
        rbKo.setEnabled(editable);
        rbNc.setEnabled(editable);
        rbOk.setEnabled(editable);
        cbOther.setEnabled(editable);
        //etOther.setEnabled(editable);
    }
}

/**
 * Class that define the view holder of a parent : the category model
 */
static class CategoryViewHolder{
    @BindView(R.id.tv_category_title)
    TextView tvCategoryTitle;

    public CategoryViewHolder(View v){
        ButterKnife.bind(this, v);
    }

}


}

推荐答案

在活动"中声明与mChecklist具有相同大小的ArrayList

Declare ArrayList with the same size in your Activity as your mChecklist has

喜欢:- ArrayList mChecklistBool = new ArrayList();

like :- ArrayList mChecklistBool = new ArrayList();

 for (int i = 0;i<Checklist.size();i++)
    {
        mChecklistBool.add(false);
    }


 When you call adapter send this ArrayList of Boolean 

  new ChecklistAdapter (mContext,mChecklist,mChecklistBool,editable);



      In Adapter class declare 

    ArrayList<Boolean> mChecklistBool;

public ChecklistAdapter(Context mContext, Checklist mChecklist, ArrayList<Boolean> mChecklistBool,boolean editable) {
this.mContext = mContext;
this.mChecklist = mChecklist;
this.isEditable = editable;
this.mChecklistBool =mChecklistBool;

}

然后在其中将视图与视图所有者绑定在一起,然后在您可以设置或重置任何位置之后获得选中的位置.

Then where you bind your view with view holder then get the checked postion and after you can set or reset any postion.

new View.OnClickListener() {
           public void onClick(View v) {
           CheckBox cb = (CheckBox) v; 
           if (mChecklist.contains(v.getTag())) {
                 int ChkPos = mChecklist.indexOf(v.getTag());
                 mChecklistBool.set(ChkPos, cb.isChecked());

          }

     }

这篇关于在ExpandableListView上滚动时,Select复选框重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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