问题
I have a custom listview with each row contaning a checkbox and text. now what i want that if any one checkbox of listview row is checked so others checkbox in other row if checked .it will be delected automatically.(i.e only one checkbox should be selected one at a time).how should i do that.
So far what i have done is as follows:
public class CustomAdapter extends BaseAdapter{
Context context;
List<String> items;
boolean array[];
public CustomAdapter(Context context, List<String> items) {
super();
this.context = context;
this.items = items;
array =new boolean[items.size()];
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v=convertView;
final int pos=position;
if(v==null)
{
v=LayoutInflater.from(context).inflate(R.layout.list,null);
}
TextView txt1=(TextView) v.findViewById(R.id.textView1);
final CheckBox chkbox=(CheckBox) v.findViewById(R.id.checkBox1);
txt1.setText(items.get(position));
int selectedindexitem=0;
chkbox.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(chkbox.isChecked())
{
array[pos]=true;
}else{
array[pos]=false;
}
}
});
chkbox.setChecked(array[pos]);
return v;
}
}
In this code i can select multiple checkbox at a time but i need only one checkbox should be checked one at a time.
回答1:
Try to change all item boolean value false exclude selected item after notify adapter and also implement ViewHolder design pattern for ListView performance :
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.list,null);
holder.txt1 = (TextView) convertView.findViewById(R.id.textView1);
holder.chkbox = (CheckBox) convertView.findViewById(R.id.checkBox1);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.txt1.setText(items.get(position));
holder.chkbox.setChecked(array[position]);
holder.chkbox.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
for (int i=0;i<array.length;i++){
if(i==position){
array[i]=true;
}else{
array[i]=false;
}
}
notifyDataSetChanged();
}
});
return convertView;
}
class ViewHolder{
TextView txt1;
CheckBox chkbox;
}
回答2:
You need to keep track of selected item and code accordingly.
public class CustomAdapter extends BaseAdapter{
Integer selected_position = -1;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Your Code
chkbox.setChecked(position==selected_position);
chkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked)
{
selected_position = position;
}
else{
selected_position = -1;
}
notifyDataSetChanged();
}
});
return convertView;
}
}
回答3:
Maintain a variable:
int checked = -1; //say
Whenever you try to check a checkbox you check this variable, if it is -1 then check the checkbox and save the position of the list item in checked variable, when you try to check other checkbox again, if the variable ain't equal to -1 you first uncheck the checkbox at the position stored in checked variable, and then check the checkbox at current position and save the current position in checked variable
回答4:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v=convertView;
final int pos=position;
if(v==null)
{
v=LayoutInflater.from(context).inflate(R.layout.list,null);
}
TextView txt1=(TextView) v.findViewById(R.id.textView1);
final CheckBox chkbox=(CheckBox) v.findViewById(R.id.checkBox1);
txt1.setText(items.get(position));
int selectedindexitem=0;
if(position==selected_position)
{
chkbox.setChecked(true);
}
else
{
chkbox.setChecked(false);
}
chkbox.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(chkbox.isChecked())
{
array[pos]=true;
selected_position = pos;
}else{
array[pos]=false;
}
}
});
chkbox.setChecked(array[pos]);
MainActivity.lv.setAdapter(new CustomAdapter(context,MainActivity.listitems));
return v;
}
回答5:
Easy to maintain your selection. Get your selection from the model.
class PropertyModel{
String VAL= "SOME VALUE"
boolean selected = false;
public String getVAL() {return VAL;}
public void setVAL(String VAL) {this.VAL = VAL;}
public boolean isSelected() {return selected;}
public void setSelected(boolean selected) {this.selected = selected;}
}
Prepare your view like this:
public class CheckBoxAdptr extends BaseAdapter{
/*
..........
*/
public View getView(int position, View view, ViewGroup parent) {
PropertyModel items = list.get(position);
View row;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_item_checkbox, null);
}
else{row = view;}
TextView T1 = (TextView) row.findViewById(R.id.list_item_1);
CheckBox checkBox = (CheckBox) row.findViewById(R.id.list_item_check_box);
T1.setText(""+items.getVAL());
if(items.isSelected()){
checkBox.setChecked(true);
}
else {checkBox.setChecked(false);}
return row;
}
}
Now in your activity or fragment set the adapter and do something like this:
final ArrayList<PropertyModel> list = getList();
CheckBoxAdptr adpt = new CheckBoxAdptr(getActivity(), list);
listview.setAdapter(adpt);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
for(int i = 0; i<list.size(); i++){
if(i!=position){
list.get(i).setSelected(false);
}
else{
list.get(i).setSelected(true);
}
}
adpt.notifyDataSetChanged();
}
});
Notice that all your work is done by adpt.notifyDataSetChanged() . Hope this helps.
回答6:
Working with getView (like most of the answers posted) was not working properly for me. It was not responsive enough. Sometimes it would uncheck the previous checkbox, sometimes not.
This worked perfectly for me:
First we need to store the position of all previously checked checkboxes:
Set<Integer> selectedPreviousPositions = new HashSet<>();
Then in the onItemClick listener we uncheck all checkboxes before checking the one we selected.
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
boolean isChecked = ((CheckBox) view.findViewById(R.id.cbSelected)).isChecked();
if (!isChecked) {
final ListView listDevices = (ListView) findViewById(R.id.lvDevices);
for (Integer pos : selectedPreviousPositions ) {
View pView = listDevices.getChildAt(pos);
if (pView != null) { // unnecessary but we never know !
((CheckBox)pView.findViewById(R.id.checkboxID)).setChecked(false);
}
}
selectedUniquePositions.add(new Integer(position));
// Now we can check the selected checkbox
((CheckBox) view.findViewById(R.id.cbSelected)).setChecked(true);
} else {
((CheckBox) view.findViewById(R.id.cbSelected)).setChecked(false);
selectedPreviousPositions.remove(new Integer(position));
}
}
回答7:
Inside the adapter, set OnClickListener() for checkBox. Whenever checkBox is clicked, store clicked checkBox position and call notifyDataSetChanged(). This will getView() method again for all views in your listview. Whenever, getView() called, you check the checkBox of previously stored postition and uncheck remaining checkboxes.
public class CustomAdapter extends ArrayAdapter<YourModelObject>
{
private int selectedCheckBoxPosition = -1;
public int getSelectedCheckBoxPosition()
{
return selectedCheckBoxPosition;
}
@Override
public View getView(final int position, View convertView, final ViewGroup parent)
{
final ViewHolder viewHolder;
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
{
convertView = layoutInflater.inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.checkBox = (CheckBox) convertView;
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
if (position == selectedCheckBoxPosition)
{
viewHolder.checkBox.setChecked(true);
Log.d(TAG, "checkbox CHECKED at pos: " + position);
}
else
{
viewHolder.checkBox.setChecked(false);
Log.d(TAG, "checkbox UNCHECKED at pos: " + position);
}
//viewHolder.checkBox.setText("sample text");
viewHolder.checkBox.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view) {
selectedCheckBoxPosition = position;
Log.d(TAG, "onClick() - set selectedCheckBoxPosition = " + position);
notifyDataSetChanged();
}
});
return convertView;
}
private class ViewHolder
{
CheckBox checkBox;
}
}
来源:https://stackoverflow.com/questions/27105222/custom-listview-with-only-one-checkbox-is-selected-one-at-a-time