I have a custom ListView with a radiogroup in each row.
When I change the checked radio button, I call a dialog with some edittext fields (using the onCheckedChanged() method). But, when i focused an edittext to write something, I lose all the checked radiobuttons which are covered by keyboard, and the group returns to the default option selected.
can someone help me?
List adapter
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ContractItemHolder cih = new ContractItemHolder();
if (row == null){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(R.layout.row_proposals_item, parent, false);
cih.setTvItemTitle((TextView)row.findViewById(R.id.textViewItemTitle));
cih.setRgItemStatus((RadioGroup)row.findViewById(R.id.radioGroupStatus));
row.setTag(cih);
}else {
cih=(ContractItemHolder)row.getTag();
}
final ContractItem ci = list.get(position);
cih.getRgItemStatus().setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
groupSel = group;
int selected = group.getCheckedRadioButtonId();
Dialog d;
switch (selected) {
case R.id.radioAccepted:
d = createDialog(context, ACCEPTED_CODE, ci, selected);
d.show();
break;
case R.id.radioRefused:
d = createDialog(context, REFUSED_CODE, ci, selected);
d.show();
break;
default:
break;
}
}
});
cih.getTvItemTitle().setText(ci.getDescItem());
return row;
}
List item layout (the row..)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp"
android:gravity="center">
<TextView
android:id="@+id/textViewItemTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Large Text"
android:layout_weight="3"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<RadioGroup
android:id="@+id/radioGroupStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="1"
android:showDividers="middle">
<RadioButton
android:id="@+id/radioNull"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Non Proposto"
android:checked="true"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<RadioButton
android:id="@+id/radioPending"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="In trattativa"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/Blue"/>
<RadioButton
android:id="@+id/radioAccepted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Accettato"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/Green"/>
<RadioButton
android:id="@+id/radioRefused"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rifiutato"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/Red"/>
</RadioGroup>
</LinearLayout>
Dialog impl
private Dialog createDialog(Context context, final int code, ContractItem item,final int selected){ //type: refused, accepted
d = new Dialog(context);
d.setTitle(item.getDescItem());
d.setContentView(R.layout.layout_dialog_prop);
d.getWindow().setLayout(900, LayoutParams.WRAP_CONTENT);
d.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
Button btnOK = (Button)d.findViewById(R.id.buttonPropOK);
Button btnCancel = (Button)d.findViewById(R.id.buttonPropCancel);
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
d.dismiss();
}
});
btnOK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
d.dismiss();
}
});
return d;
}
Dialog layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="50dp" >
<EditText
android:id="@+id/editTextDiscount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:ems="10"
android:hint="Sconto proposto"
android:inputType="number"
android:textAppearance="?android:attr/textAppearanceLarge" >
<requestFocus />
</EditText>
<Spinner
android:id="@+id/spinnerScuse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:visibility="gone" />
<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="30dp"
android:ems="10"
android:gravity="top"
android:hint="Note"
android:inputType="textMultiLine"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<View
android:id="@+id/view2"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="30dp"
android:background="@android:color/holo_blue_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/buttonPropCancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="Annulla"
android:textColor="@android:color/holo_blue_light" />
<View
android:id="@+id/view1"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@android:color/holo_blue_light" />
<Button
android:id="@+id/buttonPropOK"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="Ok"
android:textColor="@android:color/holo_blue_light" />
</LinearLayout>
</LinearLayout>
You are partially aware of the list-item view recycling process.
The
ListViewcomponent doesn’t generate view for each item in the list. So, there won’t be15of them in your case. There will be just as many as can fit on the screen. When you scroll the list, the old items, which are no longer visible, are recycled. ThegetViewis then called withconvertView != nulland the adapter is giving you an opportunity to update this recycled item view. This is done for performance reasons – just imagine an adapter having 10000 items (not a rare thing in commercial applications). Should it create all 10000 list item views? Imagine the performance you would have while scrolling such a list…In your
getView()code, you update an item view only partially – you always set item title in this line:When an fresh item view is created (i.e. the
convertView == null) the radio group has a default selection, which may be fine in your case.However, when the item view is recycled (i.e. the
convertView != null), then you:set a change listener in this line:
set item title:
But you never set the checked radio group item. That means, it will have a value which was last set for this instance of item view – not for that position. You should store that information – probably in
ContractItem, update it when the radio group item is selected and finally – retrieve it whenconvertView != nulland set selected item of the radio group to the correct value.You probably see this defect when you open up a dialog – the visible area of a
ListViewbecomes smaller as the soft keyboard opens. This causes theListViewto remove unnecessary (technically: no longer visible) item views. When you hide the soft keyboard, theListViewarea becomes larger again thus causing it to create missing item views. Unfortunately, you don’t save and restore the last selected item of the radio group and so, after creation the newly visible items have the default item selected in the radio group.