Android: Radio button in custom list view
Here are the key ideas
- when a
RadioButton
is checked we must callnotifyDataSetChanged()
, so that all views get updated. - when a
RadioButton
is checked we must set aselectedPosition
, to keep track of whichRadioButton
is selected View
s are recycled insideListView
s. Therefore, their absolute position changes in theListView
. Therefore, insideListAdapter#getView()
, we must callsetTag()
on eachRadioButton
. This allows us to determine the current position of theRadioButton
in the list when theRadioButton
is clicked.RadioButton#setChecked()
must be updated insidegetView()
for new or pre-existingView
s.
Here is an example ArrayAdapter I wrote and tested in order to demonstrate these ideas
public class MainActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// I do no use these values anywhere inside the ArrayAdapter. I could, but don't.
final Integer[] values = new Integer[] {1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,};
ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this, R.layout.row, R.id.textview, values) {
int selectedPosition = 0;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
RadioButton r = (RadioButton)v.findViewById(R.id.radiobutton);
}
TextView tv = (TextView)v.findViewById(R.id.textview);
tv.setText("Text view #" + position);
RadioButton r = (RadioButton)v.findViewById(R.id.radiobutton);
r.setChecked(position == selectedPosition);
r.setTag(position);
r.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selectedPosition = (Integer)view.getTag();
notifyDataSetChanged();
}
});
return v;
}
};
setListAdapter(adapter);
}
}
Custom ListView with RadioButton single choice
Try like this :
public class CheckedLinearLayout extends RelativeLayout implements
Checkable {
private boolean isChecked;
private List<Checkable> checkableViews;
public CheckedLinearLayout (Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
initialise(attrs);
}
public CheckedLinearLayout (Context context, AttributeSet attrs) {
super(context, attrs);
initialise(attrs);
}
public CheckedLinearLayout (Context context, int checkableId) {
super(context);
initialise(null);
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
for (Checkable c : checkableViews) {
c.setChecked(isChecked);
}
}
public void toggle() {
this.isChecked = !this.isChecked;
for (Checkable c : checkableViews) {
c.toggle();
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
final int childCount = this.getChildCount();
for (int i = 0; i < childCount; ++i) {
findCheckableChildren(this.getChildAt(i));
}
}
/**
* Read the custom XML attributes
*/
private void initialise(AttributeSet attrs) {
this.isChecked = false;
this.checkableViews = new ArrayList<Checkable>(5);
}
/**
* Add to our checkable list all the children of the view that implement the
* interface Checkable
*/
private void findCheckableChildren(View v) {
if (v instanceof Checkable) {
this.checkableViews.add((Checkable) v);
}
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
final int childCount = vg.getChildCount();
for (int i = 0; i < childCount; ++i) {
findCheckableChildren(vg.getChildAt(i));
}
}
}
}
Android ListView with RadioButton in singleChoice mode and a custom row layout
Do bear in mind that in the ListView row items are RECYCLED. This is likely to explain why actions on one row are affecting another. Dig around in Mark's book and you'll find coverage of this.
If you're using an adapter with the list, you can use getView() on an adapter to add a click handler to each row as it's created/recycled, and make sure the state is managed correctly as the row items are created and recycled.
My approach is to store the state in my own data structure, and then use getView() to mirror that in the UI as the user scrolls up and down the ListView. There may be a better solution, but that works for me.
Related Topics
How to Programmatically Pair a Bluetooth Device on Android
How to Set Android Tablayout in The Bottom of The Screen
How to Change Color of Vector Drawable Path on Button Click
Android Viewmodel Has No Zero Argument Constructor
Android: Runonuithread Vs Asynctask
How to Replace The Activity's Fragment from The Fragment Itself
Using Audiotrack in Android to Play a Wav File
How to Change System Navigation Bar Color
Firebase Console: How to Specify Click_Action for Notifications
Remove Animation/Shifting Mode from Bottomnavigationview Android
Difference Between Motionevent.Getrawx and Motionevent.Getx
How to Set a Fragment Tag by Code
Eclipse: Won't Let Me Use Android Sdk, Wrongly Claims My Adt Is Out of Date
How to Load Image as Bitmap to Glide
Adding Spinner to Actionbar (Not Navigation
How to Remove White Underline in a Searchview Widget in Toolbar Android