我对SimpleAdapter
进行了分类,为其添加了一些额外的功能,例如更改背景颜色,自定义视图和过滤。背景的事情很好,但过滤器不是。如果我使用适配器提供的SimpleFilter
则没有任何问题,所以我从源复制了这些方法并将它们放入我的适配器中。虽然我没有碰到任何东西,但在输入搜索字词时我会得到IndexOutOfBoundsException
。通常是第二个或第三个角色。
我复制了全班,但有趣的部分是CustomFilter
bindView
和getView
效果很好。实施过滤器后,它会停止工作。该异常是由第一行bindView
方法中的data.get(position)引起的,但问题必须是过滤器。
public class ChangingColorAdapter extends SimpleAdapter {
int resource;
int[] to;
List<Map<String, String>> data, mUnfilteredData;
String[] from;
Context context;
Resources res;
Filter filter;
/*
* A custom adapter which changes background colors on the elements
* and implements custom filtering
*/
public ChangingColorAdapter(Context context,
List<Map<String, String>> data, int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
this.context = context;
this.resource = resource;
this.data = data;
this.from = from;
this.to = to;
this.res = context.getResources();
}
@Override
public Filter getFilter() {
if(filter != null) return filter;
else return filter = new CustomFilter();
}
/*
* A custom filter which is copied from the simplefilter in simpleadapter.
* Changed word check from .startswith to .contains
*/
private class CustomFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mUnfilteredData == null) {
mUnfilteredData = new ArrayList<Map<String, String>>(data);
}
if (prefix == null || prefix.length() == 0) {
List<Map<String, String>> list = mUnfilteredData;
results.values = list;
results.count = list.size();
} else {
String prefixString = prefix.toString().toLowerCase();
List<Map<String, String>> unfilteredValues = mUnfilteredData;
int count = unfilteredValues.size();
ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(count);
for (int i = 0; i < count; i++) {
Map<String, ?> h = unfilteredValues.get(i);
if (h != null) {
int len = to.length;
for (int j=0; j<len; j++) {
String str = (String)h.get(from[j]);
String[] words = str.split(" ");
int wordCount = words.length;
for (int k = 0; k < wordCount; k++) {
String word = words[k];
if (word.toLowerCase().contains(prefixString)) {
newValues.add(h);
break;
}
}
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
data = (List<Map<String, String>>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(resource, parent, false);
} else {
v = convertView;
}
bindView(position, v);
if(position%2!=0) {
v.setBackgroundColor(Color.DKGRAY);
}
else {
v.setBackgroundColor(Color.BLACK);
}
return v;
}
/*
* Iterate over all elements, check which type the given view is and fill in the data
*/
private void bindView(int position, View view) {
final Map<String, String> dataSet = data.get(position);
if (dataSet == null) {
return;
}
final ViewBinder binder = getViewBinder();
final String[] from = this.from;
final int[] to = this.to;
final int count = to.length;
for (int i = 0; i < count; i++) {
final View v = view.findViewById(to[i]);
if (v != null) {
final Object data = dataSet.get(from[i]);
String text = data == null ? "" : data.toString();
if (text == null) {
text = "";
}
boolean bound = false;
if (binder != null) {
bound = binder.setViewValue(v, data, text);
}
if (!bound) {
if (v instanceof Checkable) {
if (data instanceof Boolean) {
((Checkable) v).setChecked((Boolean) data);
} else if (v instanceof TextView) {
setViewText((TextView) v, text);
} else {
throw new IllegalStateException(v.getClass().getName() +
" should be bound to a Boolean, not a " +
(data == null ? "<unknown type>" : data.getClass()));
}
} else if (v instanceof TermView) {
if(text.length()==10) {
int year = Integer.parseInt(text.substring(0,4));
if(text.substring(5, 7).equals("04")) {
setViewText((TextView) v, res.getString(R.string.summerterm) + " " + year);
}
else {
setViewText((TextView) v, res.getString(R.string.winterterm) + " " + year + "/" + (year+1));
}
}
else {
setViewText((TextView) v, text);
}
} else if (v instanceof TextView) {
setViewText((TextView) v, text);
} else if (v instanceof ImageView) {
if (data instanceof Integer) {
setViewImage((ImageView) v, (Integer) data);
} else {
setViewImage((ImageView) v, text);
}
} else {
throw new IllegalStateException(v.getClass().getName() + " is not a " +
" view that can be bounds by this SimpleAdapter");
}
}
}
}
}
}
答案 0 :(得分:3)
试试这段代码:
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
data.clear();
data.addAll((List<Map<String, String>>) results.values);
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
答案 1 :(得分:0)
无需添加filter
和bindView
方法,只需确保getView
:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
if(position%2!=0) {
v.setBackgroundColor(Color.DKGRAY);
}
else {
v.setBackgroundColor(Color.BLACK);
}
return v;
}