2016-08-03 81 views
0

我有一个listview动态添加单选按钮。 但它表现得很怪异。在滚动后,radio buttons显示在不同的行中,有些正在消失等。我在这里发布了适配器。请就如何做到这一点提出宝贵的建议。ListView与RadioButtons行为错误

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; 

    } 
} 
+0

'getView'方法太难遵循,因为它是...我强烈建议做一些重构(也许你自己在找它时发现错误) –

+0

唯一的问题是我应该在哪里放置动态单选按钮到视图?应该在(convertView == null)内部还是外部? –

回答

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,那么当getView被称为位置10时,它将只有从位置0或另一位置获得循环视图具有相同的项目视图类型。所以你可以依靠你想要的回收视图。

  • 我已经编写了代码,我已经在回收视图组上调用了getChildCount(),并且如果视图比我需要的视图更少,我添加了它们。如果它有比我需要更多的意见,我删除了额外的意见。这很丑,我不会推荐它。

此外,您还可以简化使用GridLayoutFlowLayout你的逻辑,这样你就不必指望有多少行补充?

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

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


这是因为视图回收而发生的。

您正在更改事件处理程序中的列表项视图,并且这将永远不会工作。

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

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

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

+0

任何代码片段都会有很大的帮助。通过建模你是否意味着向查看者添加单选按钮? –

+0

通过建模我的意思是在适配器中有一个变量,如'List ',其中int是所选单选按钮的ID。但首先看到我更新的答案。 –