我正在尝试将一个搜索文本字段添加到我的listview中以进行一些过滤,而我的列表适配器使用自定义对象而不是简单的字符串。搜索似乎乍一看,但如果删除过滤字符串,适配器不会更新。
以下是我的尝试:
这是我的自定义ArrayAdapter
:
public class ArticolAdapter extends OrderManagerAdapter<Articol> implements Scrollable {
private List<Articol> orderList;
private final LayoutInflater inflater;
private final Context context;
public ArticolAdapter(Context context, List<Articol> objects) {
super(context, objects);
this.inflater = LayoutInflater.from(context);
this.orderList = objects;
this.context = context;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_articol, parent, false);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.numeTV);
holder.deLivrat = (TextView) convertView.findViewById(R.id.de_livrat);
holder.articolPoza = (ImageView) convertView.findViewById(R.id.pictureCategory);
holder.observatiiTV = (TextView) convertView.findViewById(R.id.observatii);
holder.incarcatTV = (TextView) convertView.findViewById(R.id.incarcat);
holder.background = (RelativeLayout) convertView.findViewById(R.id.expandable_toggle_button);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final Articol articol = getItem(position);
holder.name.setText(articol.getNume());
System.out.println(articol.getNume());
holder.deLivrat.setText("De livrat: " + Constants.DF.format(articol.getComandat()));
holder.incarcatTV.setText("Incarcat: " + fmt(articol.getIncarcat()));
holder.observatiiTV.setText("Observatii: " + articol.getObservatii());
holder.background.setPadding(5, 5, 5, 5);
if (articol.getComandat() == articol.getIncarcat()) {
holder.background.setBackground(context.getResources().getDrawable(R.drawable.list_item_completed));
} else {
holder.background.setBackground(context.getResources().getDrawable(R.drawable.list_item_bg));
}
return convertView;
}
public static String fmt(double d) {
if (d == (int) d)
return String.format("%d", (int) d);
else
return String.format("%s", d);
}
@Override
public String getIndicatorForPosition(int childposition, int groupposition) {
return Character.toString(orderList.get(childposition).getNume().charAt(0));
}
@Override
public int getScrollPosition(int childposition, int groupposition) {
return childposition;
}
private class ViewHolder {
private TextView name, deLivrat, observatiiTV, incarcatTV;
private ImageView articolPoza;
private RelativeLayout background;
}
private List<Articol> orig;
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oReturn = new FilterResults();
final ArrayList<Articol> results = new ArrayList<Articol>();
if (orig == null) {
orig = orderList;
}
if (constraint != null) {
if (orig != null && orig.size() > 0) {
for (final Articol g : orig) {
if (g.getNume().toLowerCase()
.contains(constraint.toString())) {
results.add(g);
}
}
}
oReturn.values = results;
}
return oReturn;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
orderList = (ArrayList<Articol>) results.values;
notifyDataSetChanged();
clear();
for (Articol anOrderList : orderList) {
add(anOrderList);
}
notifyDataSetInvalidated();
}
};
}
}
OrderManagerAdapter
:
public class OrderManagerAdapter<T> extends ArrayAdapter<T> {
private final List<T> objects;
private final Object mLock;
public OrderManagerAdapter(Context context) {
super(context, 0);
objects = new ArrayList<T>();
mLock = new Object();
setNotifyOnChange(false);
}
public OrderManagerAdapter(Context context, List<T> objects) {
super(context, 0);
this.objects = objects;
mLock = new Object();
}
@Override
public void add(T object) {
synchronized (mLock) {
objects.add(object);
}
}
@Override
public void addAll(Collection<? extends T> collection) {
synchronized (mLock) {
objects.addAll(collection);
}
}
@Override
public void insert(T object, int index) {
synchronized (mLock) {
objects.add(index, object);
}
}
@Override
public void remove(T object) {
synchronized (mLock) {
objects.remove(object);
}
}
@Override
public void clear() {
synchronized (mLock) {
objects.clear();
}
}
@Override
public int getCount() {
return objects.size();
}
@Override
public T getItem(int position) {
return objects.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getPosition(T item) {
return objects.indexOf(item);
}
public List<T> getObjects() {
return objects;
}
}
这是片段中的EditText
代码:
EditText inputSearch = (EditText) rootView.findViewById(R.id.inputSearch);
inputSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
Log.d(Constants.TAG, "*** Search value changed: " + s.toString());
adapter.getFilter().filter(s);
}
});
搜索似乎是第一次过滤,在我输入一些过滤字符串的意义上,列表得到更新,但是当我清除文本时我看不到正在显示的原始列表,我得到一个空列表。
答案 0 :(得分:1)
OrderManagerAdapter不应该扩展ArrayAdapter。你重写了足够多的方法,使得ArrayAdapter在很大程度上无关紧要。另外,你没有覆盖所有的mutate方法,这意味着如果你调用其中一个方法,你可能会遇到一些非常麻烦的麻烦。
OrderManagerAdapter mutate方法都没有调用notifyDataSetChange。适配器在没有它们的情况下无法正常更新。
事实上,为什么甚至会覆盖ArrayAdapter,看起来你想要它提供的所有功能?您的OrderManagerAdapter根本没有正确完成,只会导致更多问题。您最好不要废弃OrderManagerAdapter并让ArticolAdapter扩展ArrayAdapter。
您的过滤器完全不正确:
a)在后台线程上执行,并且所有列表修改周围都没有同步块。
b)它完全更改了适配器的List引用,这意味着OrderManagerAdapter将不会指向与ArticolAdapter相同的数据列表,并且将来修改适配器的所有尝试都将失败。
c)它还会使每个过滤器后的数据无效......这基本上意味着您的适配器已经死亡,不应该再报告任何数据更改
我不确定您的最终目标是什么,但如果只需要一个简单的方法来自定义ArrayAdapter的过滤结果,只需使用this guy即可。它可以为您节省大量的麻烦。
答案 1 :(得分:0)
在将数据重新分配给适配器后,您似乎没有使用 adapter.notifyDataSetChanged(); 刷新列表视图。首先更新你的dapter,然后调用adapter.notifyDataSetChanged();在你的活动中