Android AutoCompleteTextView 与自定义适配器过滤不起作用
我有自定义 CustomerAdapter
public class CustomerAdapter extends ArrayAdapter<Customer> {
private final String MY_DEBUG_TAG = "CustomerAdapter";
private ArrayList<Customer> items;
private int viewResourceId;
public CustomerAdapter(Context context, int viewResourceId, ArrayList<Customer> items) {
super(context, viewResourceId, items);
this.items = items;
this.viewResourceId = viewResourceId;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(viewResourceId, null);
}
Customer customer = items.get(position);
if (customer != null) {
TextView customerNameLabel = (TextView) v.findViewById(R.id.customerNameLabel);
if (customerNameLabel != null) {
customerNameLabel.setText(String.valueOf(customer.getName()));
}
}
return v;
}
}
和 customer_auto
布局
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/customerNameLabel"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:padding="10dp" android:textSize="16sp"
android:textColor="#000">
</TextView>
,并且在我的 public void onCreate
AutoCompleteTextView customerAutoComplete = (AutoCompleteTextView) findViewById(R.id.autocomplete_customer);
CustomerAdapter customerAdapter = new CustomerAdapter(this, R.layout.customer_auto, customerList);
customerAutoComplete.setAdapter(customerAdapter);
和 Customer.java
public class Customer implements Parcelable {
private int id;
private String name = "";
public Customer() {
// TODO Auto-generated constructor stub
}
/**
* This will be used only by the MyCreator
*
* @param source
*/
public Customer(Parcel source) {
/*
* Reconstruct from the Parcel
*/
id = source.readInt();
name = source.readString();
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public Customer createFromParcel(Parcel source) {
return new Customer(source);
}
@Override
public Customer[] newArray(int size) {
return new Customer[size];
// TODO Auto-generated method stub
}
};
@Override
public String toString() {
return this.name;
}
}
上,但自动建议框无法正确过滤。例如;如果我在测试框中输入 an
,以 br
开头的客户就会出现!
I've the Custom CustomerAdapter
public class CustomerAdapter extends ArrayAdapter<Customer> {
private final String MY_DEBUG_TAG = "CustomerAdapter";
private ArrayList<Customer> items;
private int viewResourceId;
public CustomerAdapter(Context context, int viewResourceId, ArrayList<Customer> items) {
super(context, viewResourceId, items);
this.items = items;
this.viewResourceId = viewResourceId;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(viewResourceId, null);
}
Customer customer = items.get(position);
if (customer != null) {
TextView customerNameLabel = (TextView) v.findViewById(R.id.customerNameLabel);
if (customerNameLabel != null) {
customerNameLabel.setText(String.valueOf(customer.getName()));
}
}
return v;
}
}
and customer_auto
layout
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/customerNameLabel"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:padding="10dp" android:textSize="16sp"
android:textColor="#000">
</TextView>
and on my public void onCreate
AutoCompleteTextView customerAutoComplete = (AutoCompleteTextView) findViewById(R.id.autocomplete_customer);
CustomerAdapter customerAdapter = new CustomerAdapter(this, R.layout.customer_auto, customerList);
customerAutoComplete.setAdapter(customerAdapter);
and Customer.java
public class Customer implements Parcelable {
private int id;
private String name = "";
public Customer() {
// TODO Auto-generated constructor stub
}
/**
* This will be used only by the MyCreator
*
* @param source
*/
public Customer(Parcel source) {
/*
* Reconstruct from the Parcel
*/
id = source.readInt();
name = source.readString();
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public Customer createFromParcel(Parcel source) {
return new Customer(source);
}
@Override
public Customer[] newArray(int size) {
return new Customer[size];
// TODO Auto-generated method stub
}
};
@Override
public String toString() {
return this.name;
}
}
But the auto suggest box does not filter correctly. for eg; if i type an
in the test box customers starting with br
are showing up!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我必须重写 getFilter() 适配器的方法
这是对我有用的代码,感谢 sacoskun
I have to over-ride the getFilter() method of the Adapter
Here is the code which worked for me, thanks to sacoskun
这是我的解决方案。我觉得它比公认的更干净(不使用 3 个独立的、令人困惑的 ArrayList),并且有更多选项。即使用户输入退格键,它也应该起作用,因为它不会从
mCustomers
中删除原始条目(与接受的答案不同):This is my solution. I feel like it's a bit cleaner (doesn't use 3 separate, confusing ArrayLists) than the accepted one, and has more options. It should work even if the user types backspace, because it doesn't remove the original entries from
mCustomers
(unlike the accepted answer):我们可以简单地重写 userDefined 对象(Customer)的
toString()
方法,而不是重写适配器中的getFilter()
方法。在 toString() 中,只需根据需要过滤的内容返回字段即可。这对我有用。
在我的示例中,我根据名称进行过滤:
Instead of overriding
getFilter()
method in adapter, simply we can override thetoString()
of the userDefined object (Customer).In
toString()
just return the field based on what you need to filter. It worked for me.In my example I'm filtering based on names:
在上面的代码中,
publisHResults()
方法给出了并发修改异常......我们必须将代码修改为:
In the above code
publisHResults()
method gives the concurrent modification exception....we have to modify the code as:
也许这已经太晚了,你不需要重写所有这些函数,唯一要重写的函数是:
考虑我改变:
注意,你不应该声明新的ListItems,
因为ArrayAdapter使用它自己的mObjects,并且不过滤这个列表您的物品清单,
所以你应该使用 getItem 函数来访问项目。
那么就没有理由编写你的ArrayFilter。
Maybe this is too late, you dont need to override all of these functions , the only function to override is :
consider I change :
pay attention, you should not declare new ListItems,
because ArrayAdapter works with its own mObjects, and filter this list not your items list,
So you should use getItem function to access items.
then there is no reason to write your ArrayFilter.
我不知道你在哪里检索 getResult。我认为这种情况下没有并发修改的解决方案是:
I don't know where you retrieving the getResult. I think the solution in this case for don't have the concurrent modification is:
我希望这篇文章能够帮助人们将来实现类似的自定义功能。我基于我的微博应用程序中用于显示标签建议的适配器版本:
扩展 ArrayAdapter 以减少样板代码。实现 Filterable 以稍后更改过滤器行为。
基本上在构造函数中,您需要传递一个最初显示的列表 - 它稍后将成为一个带有过滤结果的列表(这也是对调用notifyDataSetChanged()时将考虑的列表的引用),显然是一个列表您可以在此基础上进行过滤(在我的例子中为 allTags)。我还在 getView() 中传递布局膨胀的上下文。
在上面您可以看到一个简单的视图持有者模式,在 Butterknife 的帮助下可以扩展自定义行布局。
这是我能写的最少的样板代码。您唯一关心的是方法
filterTagSuggestions
,它应该根据用户的输入返回过滤后的标签列表(CharSequence 约束
)。希望能稍微总结和整理一些必要的信息。I hope that this post will help people with implementation of a similar custom functionality in the future. I based this on my version of adapter used for displaying tag suggestions in my microblogging app:
Extending ArrayAdapter to have less boilerplate code. Implementing Filterable to change filter behavior later.
Basically in constructor you need to pass a list that will be displayed initially - it'll later become a list with filtered results (this is also a reference to a list that will be taken into consideration when calling notifyDataSetChanged()) and obviously a list on which you can base your filtering (allTags in my case). I'm also passing Context for layout inflation in getView().
Above you can see a simple view holder pattern with a little help from Butterknife to inflate a custom row layout.
This is the least boilerplate code I could write. Your only concern is method
filterTagSuggestions
that should return a filtered list of tags based on input from user (CharSequence constraint
). Hope that summarized and organized necessary info a little bit.如果您收到 ConcurrentModificationException 异常。
将 ArrayList 替换为线程安全的 CopyOnWriteArrayList。
在这里您可以找到详细信息答案
If you get ConcurrentModificationException exception.
Replace ArrayList with the thread safe CopyOnWriteArrayList.
Here you can find detatils answer
我在上面的答案中遇到了非更新和修改原始列表问题。我用这段代码解决了这个问题。
这是对于不更新和修改原始列表问题最重要的一行:
特别是那些
super(ActivityContext, ResourceID, TextViewResourceID, new ArrayList() );
我希望这个解决方案能够帮助您:)
I have non-update and modify orginal list issues from above answer. I fixed this problem with this codes.
This is most important line for non-update and modify orginal list issue:
Particularly those
super(ActivityContext, ResourceID, TextViewResourceID, new ArrayList());
I hope this solution will be help you :)