ListView与RadioButtons表现出错误

时间:2016-08-03 12:11:50

标签: android listview radio-button listview-adapter

我有listview动态添加单选按钮。 但它表现得非常错误。滚动后radio buttons会显示在不同的行中,有些正在消失等等。我已在此处发布了适配器。请提供有关如何执行此操作的宝贵建议。

public class CheckTentativePlanNSaveProductLoanEmiListAdapter extends ArrayAdapter<AddSanctionListRowDS> {

    private final Activity mContext;
    private final int mResource;
    private final ArrayList<CheckTentativePlanNsaveListRowDs> mAddSanctionListRowDS;
    private EditText mAddSanctionRowValueET;
    private  Calendar mMyCalendar;
    private ArrayList<String> mProductDetailsScreenEnteredDetails;


    public CheckTentativePlanNSaveProductLoanEmiListAdapter(Activity context, int resource, ArrayList<CheckTentativePlanNsaveListRowDs> iAddSanctionListRowObj, ArrayList<String> iAddSanctionEnteredValues)
    {
        super(context, resource);

        this.mContext                    =   context;
        this.mResource                   =   resource;
        this.mAddSanctionListRowDS        =   iAddSanctionListRowObj;

        //This depicts the values when entered or changed...
        this.mProductDetailsScreenEnteredDetails =   iAddSanctionEnteredValues;
    }

    @Override
    public int getCount() {
        return mAddSanctionListRowDS.size();
    }

    public View getView(final int position,View convertView,ViewGroup parent) {

        SaveProductListViewHolder saveProductListViewHolderObj;

        //View is creating...
        if (convertView == null) {

            convertView                                 =   LayoutInflater.from(mContext).inflate(mResource, parent, false);

            saveProductListViewHolderObj                =   new SaveProductListViewHolder();
            saveProductListViewHolderObj.key_tv         =   (TextView) convertView.findViewById(R.id.id_check_tentative_plan_n_save_product_non_loan_row_key_tv);
            saveProductListViewHolderObj.value_et       =   (EditText) convertView.findViewById(R.id.id_check_tentative_plan_n_save_product_non_loan_value_et);
            LinearLayout etParentLl                     =   (LinearLayout) convertView.findViewById(R.id.id_check_tentative_plan_n_save_product_et_non_loan_rb_ll);
            saveProductListViewHolderObj.et_parent_ll   =   etParentLl;

            RadioGroup.OnCheckedChangeListener onCheckedChangeListener = new RadioGroup.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId) {

                    for (int i = 0; i < ((LinearLayout) group.getParent()).getChildCount(); i++) {
                        RadioGroup sisterRadioGroup = (RadioGroup) ((LinearLayout) group.getParent()).getChildAt(i);
                        if (group != sisterRadioGroup) {
                            sisterRadioGroup.setOnCheckedChangeListener(null);
                            sisterRadioGroup.clearCheck();
                            sisterRadioGroup.setOnCheckedChangeListener(this);
                        }
                    }
                }
            };

            final CheckTentativePlanNsaveListRowDs currentRowDsObj   =   mAddSanctionListRowDS.get(position);


            if (currentRowDsObj.getmRadioBtnData().size() > 0) {


                //Set layout width = fill parent
                //Layout height = wrap content
                //Orientation will be vertical

                LinearLayout radioGrpParentLl                       =   new LinearLayout(mContext);
                LinearLayout.LayoutParams paramsRadioGrpParentLl    =   new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                radioGrpParentLl.setLayoutParams(paramsRadioGrpParentLl);
                radioGrpParentLl.setOrientation(LinearLayout.VERTICAL);

                float halfOfRadioCount      =   (float) currentRowDsObj.getmRadioBtnData().size() / 2;

                int noOfRadioGroupsNeeded   =   (int) Math.ceil(halfOfRadioCount);

                for (int i = 0; i < noOfRadioGroupsNeeded; i++) {

                    final RadioGroup radioGroup = new RadioGroup(mContext);
                    RadioGroup.LayoutParams paramsRadio = new RadioGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                    radioGroup.setOrientation(RadioGroup.HORIZONTAL);
                    radioGroup.setLayoutParams(paramsRadio);


                    //Add 2 Radio Buttons...

                    //Left Radio Button...

                    RadioButton leftRadioButtonInCurrentRadioGroup = new RadioButton(mContext);
                    RadioGroup.LayoutParams paramsLeftRadioBtnInCurrentRadioGroup = new RadioGroup.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);
                    leftRadioButtonInCurrentRadioGroup.setLayoutParams(paramsLeftRadioBtnInCurrentRadioGroup);
                    paramsLeftRadioBtnInCurrentRadioGroup.weight = 1f;
                    leftRadioButtonInCurrentRadioGroup.setTypeface(Typeface.DEFAULT_BOLD);
                    leftRadioButtonInCurrentRadioGroup.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                            if (isChecked) {
                                //If checked, set the value...
                                int currentIndex = 0;

                                for (int i = 0; i < position; i++) {
                                    if (currentRowDsObj.ismIsInputTypeNumeric() || currentRowDsObj.ismIsInputTypeText() || currentRowDsObj.ismIsDatePickerToBeShown()) {
                                        currentIndex++;
                                    }

                                    if (currentRowDsObj.getmRadioBtnData().size() != 0) {
                                        //A space allocated for unit...
                                        currentIndex++;
                                    }
                                }

                                if (currentRowDsObj.ismIsInputTypeText() || currentRowDsObj.ismIsInputTypeNumeric() || currentRowDsObj.ismIsDatePickerToBeShown()) {
                                    //If current position has an allocation for entering value..
                                    //Increment a space for that as well..
                                    currentIndex++;
                                }

                                mProductDetailsScreenEnteredDetails.remove(currentIndex);
                                mProductDetailsScreenEnteredDetails.add(currentIndex, buttonView.getText().toString());
                            } else {
                                //Do nothing..
                            }
                        }
                    });

                    String leftRadionBtnLabel = currentRowDsObj.getmRadioBtnData().get(2 * i).getLabel();
                    leftRadioButtonInCurrentRadioGroup.setText(leftRadionBtnLabel);
                    radioGroup.addView(leftRadioButtonInCurrentRadioGroup);

                    if (((2 * i) + 1) < currentRowDsObj.getmRadioBtnData().size()) {

                        //At the end there is a chance that only one radio button has to be shown..
                        //The above condition avoids trying to add..

                        //Right Radio Button...
                        RadioButton rightRadioButtonInCurrentRadioGroup = new RadioButton(mContext);
                        RadioGroup.LayoutParams paramsRightRadioBtnInCurrentRadioGroup = new RadioGroup.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);
                        rightRadioButtonInCurrentRadioGroup.setLayoutParams(paramsLeftRadioBtnInCurrentRadioGroup);
                        paramsRightRadioBtnInCurrentRadioGroup.weight = 1f;
                        rightRadioButtonInCurrentRadioGroup.setTypeface(Typeface.DEFAULT_BOLD);
                        String rightRadioBtnLabel = currentRowDsObj.getmRadioBtnData().get((2 * i) + 1).getLabel();
                        rightRadioButtonInCurrentRadioGroup.setText(rightRadioBtnLabel);
                        rightRadioButtonInCurrentRadioGroup.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                            @Override
                            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                                if (isChecked) {
                                    //If checked, set the value...
                                    int currentIndex = 0;

                                    for (int i = 0; i < position; i++) {
                                        if (currentRowDsObj.ismIsInputTypeNumeric() || currentRowDsObj.ismIsInputTypeText() || currentRowDsObj.ismIsDatePickerToBeShown()) {
                                            currentIndex++;
                                        }

                                        if (currentRowDsObj.getmRadioBtnData().size() != 0) {
                                            //A space allocated for unit...
                                            currentIndex++;
                                        }
                                    }

                                    if (currentRowDsObj.ismIsInputTypeText() || currentRowDsObj.ismIsInputTypeNumeric() || currentRowDsObj.ismIsDatePickerToBeShown()) {
                                        //If current position has an allocation for entering value..
                                        //Increment a space for that as well..
                                        currentIndex++;
                                    }

                                    mProductDetailsScreenEnteredDetails.remove(currentIndex);
                                    mProductDetailsScreenEnteredDetails.add(currentIndex, buttonView.getText().toString());
                                } else {
                                    //Do nothing..
                                }
                            }
                        });

                        radioGroup.addView(rightRadioButtonInCurrentRadioGroup);
                        radioGroup.setOnCheckedChangeListener(onCheckedChangeListener);
                    }

                    radioGrpParentLl.addView(radioGroup);
                }
                //Add RadioButton Group to the Parent Linear Layout..
                saveProductListViewHolderObj.et_parent_ll.addView(radioGrpParentLl);
            }

            convertView.setTag(saveProductListViewHolderObj);


        }else{
            saveProductListViewHolderObj            =   (SaveProductListViewHolder)convertView.getTag();
        }

        final CheckTentativePlanNsaveListRowDs currentRowDsObj   =   mAddSanctionListRowDS.get(position);

        saveProductListViewHolderObj.key_tv.setText(currentRowDsObj.getmEnterDetailsKey());
        saveProductListViewHolderObj.value_et.setHint(currentRowDsObj.getmEnterDetailsValue());
        saveProductListViewHolderObj.value_et.setFocusable(true);


        //Based on the input type...
        //Set the text change listener...

        if(currentRowDsObj.ismIsInputTypeNumeric()){

            saveProductListViewHolderObj.value_et.setInputType(InputType.TYPE_CLASS_NUMBER);

            saveProductListViewHolderObj.value_et.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {

                }

                @Override
                public void afterTextChanged(Editable s) {
                    int currentIndex    =   0;

                    for(int i=0;i<position;i++){
                        if(currentRowDsObj.ismIsInputTypeNumeric()||currentRowDsObj.ismIsInputTypeText()||currentRowDsObj.ismIsDatePickerToBeShown()) {
                            currentIndex++;
                        }

                        if(currentRowDsObj.getmRadioBtnData().size()!=0) {
                            //A space allocated for unit...
                            currentIndex++;
                        }
                    }

                    mProductDetailsScreenEnteredDetails.remove(currentIndex);
                    mProductDetailsScreenEnteredDetails.add(currentIndex,s.toString());

                }
            });

        }else if(currentRowDsObj.ismIsInputTypeText()){

            saveProductListViewHolderObj.value_et.setInputType(InputType.TYPE_CLASS_TEXT);

            saveProductListViewHolderObj.value_et.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {

                }

                @Override
                public void afterTextChanged(Editable s) {
                    int currentIndex    =   0;

                    for(int i=0;i<position;i++){
                        if(currentRowDsObj.ismIsInputTypeNumeric()||currentRowDsObj.ismIsInputTypeText()||currentRowDsObj.ismIsDatePickerToBeShown()) {
                            currentIndex++;
                        }

                        if(currentRowDsObj.getmRadioBtnData().size()!=0){
                            //A space allocated for unit...
                            currentIndex++;
                        }
                    }

                    mProductDetailsScreenEnteredDetails.remove(currentIndex);
                    mProductDetailsScreenEnteredDetails.add(currentIndex,s.toString());
                }
            });

        }else if(currentRowDsObj.ismIsDatePickerToBeShown()){

            //Here whether number or text...
            //Doesnot matter...
            saveProductListViewHolderObj.value_et.setInputType(InputType.TYPE_CLASS_NUMBER);

            saveProductListViewHolderObj.value_et.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {

                }

                @Override
                public void afterTextChanged(Editable s) {

                    //Calculate position dynamically here...

                    int currentIndex    =   0;

                    for(int i=0;i<position;i++){
                        if(currentRowDsObj.ismIsInputTypeNumeric()||currentRowDsObj.ismIsInputTypeText()||currentRowDsObj.ismIsDatePickerToBeShown()) {
                            currentIndex++;
                        }

                        if(currentRowDsObj.getmRadioBtnData().size()!=0){
                            //A space allocated for unit...
                            currentIndex++;
                        }
                    }

                    mProductDetailsScreenEnteredDetails.remove(currentIndex);
                    mProductDetailsScreenEnteredDetails.add(currentIndex,s.toString());

                }
            });

        }else{
            saveProductListViewHolderObj.value_et.setVisibility(View.GONE);
        }

        return convertView;

    }

    static class SaveProductListViewHolder {

        public TextView key_tv;
        public EditText value_et;
        public LinearLayout et_parent_ll;

    }
}

1 个答案:

答案 0 :(得分:1)

编辑:既然我正在更深入地解析您的代码,我认为您有一个更大的问题,因为您正在动态地向列表项添加无线电组。动态添加/删除列表项中的视图会让您头疼。

这就是我的意思:列表项的模型是currentRowDsObj,你来到这里:

        final CheckTentativePlanNsaveListRowDs currentRowDsObj = 
                mAddSanctionListRowDS.get(position);

然后,您的模型中有一些内容可以确定您要添加的广播组数量:

            float halfOfRadioCount =
                    (float) currentRowDsObj.getmRadioBtnData().size() / 2;

            int noOfRadioGroupsNeeded =
                     (int) Math.ceil(halfOfRadioCount);

所以,让我们说你位置0的列表项有mRadioBtnData.size()== 4.你要在列表项中添加两个无线电组。

但是现在假设用户正在滚动并且他们到达位置10.位置0已经滚动离开屏幕以便它被回收。位置10的列表项具有mRadioBtnData.size()== 6,因此您应该有三个无线电组。位置10的getView从位置0接收回收的视图。但是,您的回收视图上次只有两组!

你将不得不考虑如何实现这一目标。以下是几个选项:

  • 项目可能拥有的最大单选按钮数量是多少?如果它只是,例如,5,您可以有五种不同的项目视图类型。您可以使用不同的布局为每个项目视图类型进行充气。然后,您将覆盖getItemViewType()以根据您拥有的单选按钮的数量返回不同的类型值。这种方法的工作方式是,如果列表视图知道位置0和位置10都有一个项目视图类型== 2,那么当为位置10调用getView时,它将获取从位置0或具有相同项目视图类型的其他位置的回收视图。因此,您可以依靠您想要的方式依赖回收的视图。

  • 我已经编写了代码,我在回收的视图组中调用了getChildCount(),如果它的视图比我需要的少,我就添加了它们。如果它有比我需要的更多的视图我删除了额外的。这非常难看,我不推荐它。

另外,您可以使用GridLayoutFlowLayout来简化逻辑,这样您就不必计算要添加的行数吗?

另一点是,RadioGroupLinearLayout,因此它希望所有单选按钮都在一行或一列中。由于你有一个单选按钮网格,我想你最终必须自己取消选择以前选择的按钮。当单选按钮本身是RecyclerView中的列表项时,我也编写了这样做的代码。

希望其中一些有所帮助。重新思考你的设计,并在代码中再次挥杆;如果你仍然需要帮助,请发布另一个问题。

由于视图回收,这种情况正在发生。

您正在从事件处理程序中更改列表项视图,这将永远不会起作用。

使用适配器,您始终需要从Controller(事件处理程序)更改Model并从Model(getView)更新View。

据我所知,您似乎没有任何模拟单选按钮状态的数据结构,因此您需要将其添加到适配器。使用该数据设置getView中视图的选中状态,然后更新onCheckedChangedListener中的数据并调用适配器上的notifyDataSetChanged

通常,列表项视图中可以更改的任何内容都必须包含某种对应的模型数据。