我有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;
}
}
答案 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()
,如果它的视图比我需要的少,我就添加了它们。如果它有比我需要的更多的视图我删除了额外的。这非常难看,我不推荐它。
另外,您可以使用GridLayout
或FlowLayout
来简化逻辑,这样您就不必计算要添加的行数吗?
另一点是,RadioGroup
是LinearLayout
,因此它希望所有单选按钮都在一行或一列中。由于你有一个单选按钮网格,我想你最终必须自己取消选择以前选择的按钮。当单选按钮本身是RecyclerView
中的列表项时,我也编写了这样做的代码。
希望其中一些有所帮助。重新思考你的设计,并在代码中再次挥杆;如果你仍然需要帮助,请发布另一个问题。
由于视图回收,这种情况正在发生。
您正在从事件处理程序中更改列表项视图,这将永远不会起作用。
使用适配器,您始终需要从Controller(事件处理程序)更改Model并从Model(getView)更新View。
据我所知,您似乎没有任何模拟单选按钮状态的数据结构,因此您需要将其添加到适配器。使用该数据设置getView
中视图的选中状态,然后更新onCheckedChangedListener
中的数据并调用适配器上的notifyDataSetChanged
。
通常,列表项视图中可以更改的任何内容都必须包含某种对应的模型数据。