问题
I have a custom listview which display an image, textview and radio button. I need to select only one item (i.e RadioButton)at a time. I attached a textwatcher to this listview and everything working fine.
The problem goes here
- Lets assume that in the listview i selected the first radio button.
- I performed search option in EditText box show that it filters the listview items and the filtered list item/items will be displayed at the first position.
- Here the filterd item in the first positon is also getting checked (because it was selected before)
Is it require to save the state of radio button before filtering ?
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if ( row == null) {
// Log.d(tag,"Starting XML Row Inflation");
LayoutInflater inflater = (LayoutInflater) this.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.custom_row_view_user, parent, false);
Log.d(tag,"Successfully completed XML Row Inflation for positon"+position);
}
// Get item
final Contact contact = getItem(position);
contactIcon = (ImageView) row.findViewById(R.id.image_icon);
name = (TextView) row.findViewById(R.id.textviewname);
name.setText(contact.name);
rb = (RadioButton) row.findViewById(R.id.radiobutton1);
rb.setEnabled(true);
String imgFilePath = DIR + contact.imageId;
try {
Bitmap bitmap = BitmapFactory.decodeStream(this.context.getResources().getAssets().open(imgFilePath));
contactIcon.setImageBitmap(bitmap);
} catch(IOException e) {
e.printStackTrace();
}
return row;
}
// Filter function
@Override
public Filter getFilter() {
if (filter == null) {
filter = new ContactFilter();
}
return filter;
}
private class ContactFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if( prefix == null || prefix.length() == 0) {
synchronized (this) {
results.values = originalContacts;
results.count = originalContacts.size();
}
} else {
synchronized (this) {
String prefixString = prefix.toString().toLowerCase();
final ArrayList<Contact> filteredItems = new ArrayList<Contact>();
final ArrayList<Contact> localItems = new ArrayList<Contact>();
localItems.addAll(originalContacts);
final int count = localItems.size();
for ( int i=0; i<count; i++) {
final Contact contact = localItems.get(i);
final String contactName = contact.name.toString().toLowerCase();
if ( contactName.startsWith(prefixString) ) {
filteredItems.add(contact);
} else {
}
}
results.values = filteredItems;
results.count = filteredItems.size();
} // end of synchronized.
}
return results;
}
@Override
protected void publishResults(CharSequence prefix,
FilterResults results) {
synchronized (this) {
@SuppressWarnings("unchecked")
final ArrayList<Contact> localItems = (ArrayList<Contact>)results.values;
notifyDataSetChanged();
clear();
for( Iterator<Contact> iterator = localItems.iterator(); iterator.hasNext();) {
Contact index = (Contact) iterator.next();
add(index);
}
} // end of syncronized
}
}
Contact type class
public class Contact {
public String name;
public String imageId;
public String type;
public boolean isSelected;
public boolean useDefaultKey;
public boolean flag;
public Contact() {
}
public Contact(String name, String type, String resouceFilePath) {
this.name = name;
this.type = type;
this.imageId = resouceFilePath;
this.isSelected = false;
this.useDefaultKey = true;
this.flag = false;
}
@Override
public String toString() {
return this.name;
}
public boolean getCheckeBoxStatus() {
return isSelected;
}
}
And i implemented LinearLayout checkable method as follows
public class CheckableLinearLayout extends LinearLayout implements Checkable{
private RadioButton rb;
public CheckableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// find checked text view
int childCount = getChildCount();
for (int i = 0; i < childCount; ++i) {
View v = getChildAt(i);
if (v instanceof RadioButton) {
rb = (RadioButton)v;
}
}
}
@Override
public boolean isChecked() {
return rb != null ? rb.isChecked() : false;
}
@Override
public void setChecked(boolean checked) {
if (rb != null) {
// Toast.makeText(getContext(), "Clicked radio buttton", Toast.LENGTH_LONG).show();
rb.setChecked(checked);
}
}
@Override
public void toggle() {
if (rb != null) {
rb.toggle();
rb.setChecked(false);
}
}}
Any help is greatly appreciated..
回答1:
You must be trying to make radiobutton checked by using position parameter of the getView() method of your adapter. Instead try to set radiobutton checked based on some Id.
EDIT:
From your code study, I came to know that you have implemented this example:
http://tokudu.com/2010/android-checkable-linear-layout/
and as I had assumed earlier, the radio button check state is dependent on position of the row in listview but not actual item in the listview whose position is meant to be changed on filter. I have done couple of changes in your code and now the listview item check is not based on position of the item, but item itself(by matching the name of contact).
Changes in the code are as follows:
HelloListViewActivity:
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> av, View view, int position,
long id) {
o = av.getItemAtPosition(position);
String name = ((Contact) o).name;
selectedName = name;
ContactAdapter :
static boolean isContactChecked = false;
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
final Contact contact = getItem(position);
if(contact.name.equalsIgnoreCase(HelloListViewActivity.selectedName))
isContactChecked = true;
else
isContactChecked= false;
CheckableLinearLayout :
@Override
public void setChecked(boolean checked) {
if (rb != null) {
// rb.setChecked(checked);
rb.setChecked(ContactAdapter.isContactChecked);
}
}
来源:https://stackoverflow.com/questions/8771083/radiobutton-state-updation-after-filtering-in-custom-listview