在本教程(http://www.tutorialsbuzz.com/2014/08/filter-custom-listviewbaseadapter.html)中,我可以根据ListView
输入过滤EditText
中的项目:
结果与预期完美结合。但是,当我尝试将CheckBox
放入ListView
项时,事情就会失控。以下是我对教程中源代码的修改。
Country.java
public class Country {
String name;
String iso_code;
int flag;
Boolean checked;
Country(String name, String iso_code, int flag, Boolean checked) {
this.name = name;
this.iso_code = iso_code;
this.flag = flag;
this.checked = checked;
}
public String getIso_code() {
return iso_code;
}
public void setIso_code(String iso_code) {
this.iso_code = iso_code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
}
public Boolean getChecked() {
return checked;
}
public void setChecked(Boolean checked) {
this.checked = checked;
}
}
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="2dp">
<ImageView
android:id="@+id/flag"
android:layout_width="80dp"
android:layout_height="70dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_toRightOf="@+id/flag"
android:paddingBottom="10dp"
android:text="txt"
android:textColor="#000000"
android:textSize="20sp"/>
<TextView
android:id="@+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/name"
android:layout_below="@+id/name"
android:layout_marginLeft="5dp"
android:text="txt"
android:textColor="#000000"
android:textSize="16sp"/>
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="16dp"/>
</RelativeLayout>
CustomAdapter.java
public class CustomAdapter extends BaseAdapter implements Filterable {
Context context;
ArrayList<Country> countrylist;
ArrayList<Country> mStringFilterList;
ValueFilter valueFilter;
CustomAdapter(Context context , ArrayList<Country> countrylist) {
this.context = context;
this.countrylist = countrylist;
mStringFilterList = countrylist;
}
@Override
public int getCount() {
return countrylist.size();
}
@Override
public Object getItem(int position) {
return countrylist.get(position);
}
@Override
public long getItemId(int position) {
return countrylist.indexOf(getItem(position));
}
@Override
public View getView(int position , View convertView , ViewGroup parent ) {
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, null);
TextView name_tv = (TextView) convertView.findViewById(R.id.name);
TextView iso_tv = (TextView) convertView.findViewById(R.id.code);
ImageView iv = (ImageView) convertView.findViewById(R.id.flag);
CheckBox cb = (CheckBox) convertView.findViewById(R.id.checkBox);
Country country = countrylist.get(position);
name_tv.setText(country.getName());
iso_tv.setText(country.getIso_code());
iv.setImageResource(country.getFlag());
cb.setChecked(country.getChecked());
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
country.setChecked(isChecked);
}
});
}
return convertView;
}
@Override
public Filter getFilter() {
if (valueFilter == null) {
valueFilter = new ValueFilter();
}
return valueFilter;
}
private class ValueFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<Country> filterList = new ArrayList<Country>();
for (int i = 0; i < mStringFilterList.size(); i++) {
if ( (mStringFilterList.get(i).getName().toUpperCase() )
.contains(constraint.toString().toUpperCase())) {
Country country = new Country(mStringFilterList.get(i)
.getName() , mStringFilterList.get(i)
.getIso_code() , mStringFilterList.get(i)
.getFlag());
filterList.add(country);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = mStringFilterList.size();
results.values = mStringFilterList;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
countrylist = (ArrayList<Country>) results.values;
notifyDataSetChanged();
}
}
}
过滤时,CheckBox
的状态几乎总是随机跳跃。我假设因为Country
中的值已在运行时更改。知道如何以正确的方式实现这一点吗?
答案 0 :(得分:0)
如果convertView已存在,则不会更新视图。你应该这样做,唯一要忽略的是重新充气。 (顺便说一下,视图模式会大大改善这段代码。)
因为您永远不会更新视图,所以它意味着它会显示之前该位置的数据。
@Override
public View getView(int position , View convertView , ViewGroup parent ) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
CheckBox cb = (ImageView) convertView.findViewById(R.id.checkBox);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, null);
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
country.setChecked(isChecked);
}
});
}
TextView name_tv = (TextView) convertView.findViewById(R.id.name);
...
cb.setChecked(country.getChecked());
return convertView;
}
上面的代码在我看来它应该可以解决您的问题,但是对格式化感到宽容,我正在通过手机进行编辑。将来你可以使用它来查看可检查的界面和列表视图,应该为你节省一些代码(并且让人头痛)