Android 如何使用ArrayAdapter为ListView编写自定义筛选器
我有一个ListView,它连接到ArrayAdapter,其中Artist是我的一个简单类,它只有一个id和一个名称 现在我想筛选ListView,因此我调用:Android 如何使用ArrayAdapter为ListView编写自定义筛选器,android,listview,android-arrayadapter,Android,Listview,Android Arrayadapter,我有一个ListView,它连接到ArrayAdapter,其中Artist是我的一个简单类,它只有一个id和一个名称 现在我想筛选ListView,因此我调用: artistAdapter.getFilter().filter("bla", new Filter.FilterListener() { public void onFilterComplete(int count) { Log.d(Config.LOG_TAG, "filter complete! coun
artistAdapter.getFilter().filter("bla", new Filter.FilterListener() {
public void onFilterComplete(int count) {
Log.d(Config.LOG_TAG, "filter complete! count: " + count); // returns 8
Log.d(Config.LOG_TAG, "adapter count: " + artistAdapter.getCount()); // return 1150
}
});
第一条debug语句打印8的计数。这是以“bla”开头的listitems的正确计数,但适配器没有得到它。第二条debug语句打印1150个项目。这是列表中项目的完整数量
因此,过滤器不会告诉适配器它已经过滤了底层数据
我现在想知道:我是否在适配器中编写了一些代码,以便它从过滤器中获取更新?我必须编写自定义筛选器吗?我该怎么办?我想你可以使用
notifyDataSetChanged()在filterComplete方法中的code>。实际上
我注意到我应该在performFiltering中使用“originalItems”列表来构建新的过滤列表
这将修复您看到的有关更改过滤器中文本的任何问题。例如,你搜索“面包”,然后退格到只有一个“B”,你应该看到所有的“B”。在我原来的帖子里,你不会有
private class GlycaemicIndexItemAdapter extends ArrayAdapter<GlycaemicIndexItem> {
private ArrayList<GlycaemicIndexItem> items;
private ArrayList<GlycaemicIndexItem> originalItems = new ArrayList<GlycaemicIndexItem>();
private GlycaemicIndexItemFilter filter;
private final Object mLock = new Object();
public GlycaemicIndexItemAdapter(Context context, int textViewResourceId, ArrayList<GlycaemicIndexItem> newItems) {
super(context, textViewResourceId, newItems);
this.items = newItems;
cloneItems(newItems);
}
protected void cloneItems(ArrayList<GlycaemicIndexItem> items) {
for (Iterator iterator = items.iterator(); iterator
.hasNext();) {
GlycaemicIndexItem gi = (GlycaemicIndexItem) iterator.next();
originalItems.add(gi);
}
}
@Override
public int getCount() {
synchronized(mLock) {
return items!=null ? items.size() : 0;
}
@Override
public GlycaemicIndexItem getItem(int item) {
GlycaemicIndexItem gi = null;
synchronized(mLock) {
gi = items!=null ? items.get(item) : null;
}
return gi;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
GlycaemicIndexItem i = null;
synchronized(mLock) {
i = items.get(position);
}
if (i != null) {
TextView tt = (TextView) v.findViewById(R.id.rowText);
TextView bt = (TextView) v.findViewById(R.id.rowText2);
if (tt != null) {
tt.setText("Name: "+i.getName());
}
if(bt != null){
bt.setText("GI Value: " + i.getGlycaemicIndex());
}
}
return v;
}
/**
* Implementing the Filterable interface.
*/
public Filter getFilter() {
if (filter == null) {
filter = new GlycaemicIndexItemFilter();
}
return filter;
}
/**
* Custom Filter implementation for the items adapter.
*
*/
private class GlycaemicIndexItemFilter extends Filter {
protected FilterResults performFiltering(CharSequence prefix) {
// Initiate our results object
FilterResults results = new FilterResults();
// No prefix is sent to filter by so we're going to send back the original array
if (prefix == null || prefix.length() == 0) {
synchronized (mLock) {
results.values = originalItems;
results.count = originalItems.size();
}
} else {
synchronized(mLock) {
// Compare lower case strings
String prefixString = prefix.toString().toLowerCase();
final ArrayList<GlycaemicIndexItem> filteredItems = new ArrayList<GlycaemicIndexItem>();
// Local to here so we're not changing actual array
final ArrayList<GlycaemicIndexItem> localItems = new ArrayList<GlycaemicIndexItem>();
localItems.addAll(originalItems);
final int count = localItems.size();
for (int i = 0; i < count; i++) {
final GlycaemicIndexItem item = localItems.get(i);
final String itemName = item.getName().toString().toLowerCase();
// First match against the whole, non-splitted value
if (itemName.startsWith(prefixString)) {
filteredItems.add(item);
} else {} /* This is option and taken from the source of ArrayAdapter
final String[] words = itemName.split(" ");
final int wordCount = words.length;
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefixString)) {
newItems.add(item);
break;
}
}
} */
}
// Set and return
results.values = filteredItems;
results.count = filteredItems.size();
}//end synchronized
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence prefix, FilterResults results) {
//noinspection unchecked
synchronized(mLock) {
final ArrayList<GlycaemicIndexItem> localItems = (ArrayList<GlycaemicIndexItem>) results.values;
notifyDataSetChanged();
clear();
//Add the items back in
for (Iterator iterator = localItems.iterator(); iterator
.hasNext();) {
GlycaemicIndexItem gi = (GlycaemicIndexItem) iterator.next();
add(gi);
}
}//end synchronized
}
}
}
private class GlycaemicIndexItemAdapter扩展了ArrayAdapter{
私有ArrayList项;
private ArrayList originalItems=new ArrayList();
私有血糖指数过滤器;
私有最终对象mLock=新对象();
public GlycaemicIndexItemAdapter(上下文、int-textViewResourceId、ArrayList-newItems){
super(上下文、textViewResourceId、newItems);
this.items=newItems;
克隆门(新项);
}
受保护的空克隆项(ArrayList项){
for(迭代器迭代器=items.Iterator();迭代器
.hasNext();){
GlycaemicIndexItem gi=(GlycaemicIndexItem)迭代器.next();
添加(gi);
}
}
@凌驾
public int getCount(){
已同步(mLock){
返回项!=null?项。大小():0;
}
@凌驾
公共血糖指数getItem(int项){
血糖指数gi=null;
已同步(mLock){
gi=items!=null?items.get(item):null;
}
返回gi;
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
视图v=转换视图;
如果(v==null){
LayoutInflater vi=(LayoutInflater)getSystemService(Context.LAYOUT\u INFLATER\u SERVICE);
v=vi.充气(R.布局.行,空);
}
血糖指数i=null;
已同步(mLock){
i=项目。获取(位置);
}
如果(i!=null){
TextView tt=(TextView)v.findViewById(R.id.rowText);
TextView bt=(TextView)v.findViewById(R.id.rowText2);
如果(tt!=null){
tt.setText(“Name:+i.getName());
}
如果(bt!=null){
bt.setText(“GI值:+i.getGlycaemicIndex());
}
}
返回v;
}
/**
*实现可过滤接口。
*/
公共过滤器getFilter(){
if(filter==null){
filter=新的血糖指数xitemfilter();
}
回流过滤器;
}
/**
*items适配器的自定义筛选器实现。
*
*/
私有类GlycaemicIndexItemFilter扩展了筛选器{
受保护的筛选器结果执行筛选(字符序列前缀){
//启动我们的结果对象
FilterResults results=新的FilterResults();
//没有前缀发送到筛选依据,因此我们将发送回原始数组
if(prefix==null | | prefix.length()==0){
已同步(mLock){
结果。值=原始值;
results.count=originalItems.size();
}
}否则{
已同步(mLock){
//比较小写字符串
字符串prefixString=prefix.toString().toLowerCase();
final ArrayList filteredItems=新的ArrayList();
//本地到这里,所以我们不改变实际数组
final ArrayList localItems=新的ArrayList();
localItems.addAll(originalItems);
最终整数计数=localItems.size();
for(int i=0;i package com.tilleytech.android.myhealthylife;
import java.util.ArrayList;
import java.util.Iterator;
import android.app.ListActivity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.ListView;
import android.widget.TextView;
public class GlycaemicIndexAtoZActivity extends ListActivity {
/** Called when the activity is first created. */
private GlycaemicIndexItemAdapter giAdapter;
private TextWatcher filterTextWatcher;
private EditText filterText = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.giatoz);
ListView lv = getListView();
lv.setTextFilterEnabled(true);
// By using setAdapter method in listview we an add string array in list.
ArrayList<GlycaemicIndexItem> list = getListItems();
giAdapter = new GlycaemicIndexItemAdapter(this, R.layout.row, list);
giAdapter.notifyDataSetChanged();
setListAdapter(giAdapter);
filterText = (EditText)findViewById(R.id.GI_AtoZSearchEditText);
filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
giAdapter.getFilter().filter(s); //Filter from my adapter
giAdapter.notifyDataSetChanged(); //Update my view
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
};
filterText.addTextChangedListener(filterTextWatcher);
}
private ArrayList<GlycaemicIndexItem> getListItems() {
ArrayList<GlycaemicIndexItem> result = new ArrayList<GlycaemicIndexItem>();
Resources res = getResources();
//Get our raw strings
String[] array = res.getStringArray(R.array.GIList);
for (int i = 0; i < array.length; i++) {
GlycaemicIndexItem gi = new GlycaemicIndexItem();
gi.setName(array[i]);
gi.setGlycaemicIndex(1);
result.add(gi);
}
return result;
}
private class GlycaemicIndexItemAdapter extends ArrayAdapter<GlycaemicIndexItem> {
private ArrayList<GlycaemicIndexItem> items;
private ArrayList<GlycaemicIndexItem> originalItems = new ArrayList<GlycaemicIndexItem>();
private GlycaemicIndexItemFilter filter;
private final Object mLock = new Object();
public GlycaemicIndexItemAdapter(Context context, int textViewResourceId, ArrayList<GlycaemicIndexItem> newItems) {
super(context, textViewResourceId, newItems);
this.items = newItems;
cloneItems(newItems);
}
protected void cloneItems(ArrayList<GlycaemicIndexItem> items) {
for (Iterator iterator = items.iterator(); iterator
.hasNext();) {
GlycaemicIndexItem gi = (GlycaemicIndexItem) iterator.next();
originalItems.add(gi);
}
}
@Override
public int getCount() {
synchronized(mLock) {
return items!=null ? items.size() : 0;
}
}
@Override
public GlycaemicIndexItem getItem(int item) {
GlycaemicIndexItem gi = null;
synchronized(mLock) {
gi = items!=null ? items.get(item) : null;
}
return gi;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
GlycaemicIndexItem i = null;
synchronized(mLock) {
i = items.get(position);
}
if (i != null) {
TextView tt = (TextView) v.findViewById(R.id.rowText);
TextView bt = (TextView) v.findViewById(R.id.rowText2);
if (tt != null) {
tt.setText("Name: "+i.getName());
}
if(bt != null){
bt.setText("GI Value: " + i.getGlycaemicIndex());
}
}
return v;
}
/**
* Implementing the Filterable interface.
*/
public Filter getFilter() {
if (filter == null) {
filter = new GlycaemicIndexItemFilter();
}
return filter;
}
/**
* Custom Filter implementation for the items adapter.
*
*/
private class GlycaemicIndexItemFilter extends Filter {
protected FilterResults performFiltering(CharSequence prefix) {
// Initiate our results object
FilterResults results = new FilterResults();
// No prefix is sent to filter by so we're going to send back the original array
if (prefix == null || prefix.length() == 0) {
synchronized (mLock) {
results.values = originalItems;
results.count = originalItems.size();
}
} else {
synchronized(mLock) {
// Compare lower case strings
String prefixString = prefix.toString().toLowerCase();
final ArrayList<GlycaemicIndexItem> filteredItems = new ArrayList<GlycaemicIndexItem>();
// Local to here so we're not changing actual array
final ArrayList<GlycaemicIndexItem> localItems = new ArrayList<GlycaemicIndexItem>();
localItems.addAll(originalItems);
final int count = localItems.size();
for (int i = 0; i < count; i++) {
final GlycaemicIndexItem item = localItems.get(i);
final String itemName = item.getName().toString().toLowerCase();
// First match against the whole, non-splitted value
if (itemName.startsWith(prefixString)) {
filteredItems.add(item);
} else {} /* This is option and taken from the source of ArrayAdapter
final String[] words = itemName.split(" ");
final int wordCount = words.length;
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefixString)) {
newItems.add(item);
break;
}
}
} */
}
// Set and return
results.values = filteredItems;
results.count = filteredItems.size();
}//end synchronized
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence prefix, FilterResults results) {
//noinspection unchecked
synchronized(mLock) {
final ArrayList<GlycaemicIndexItem> localItems = (ArrayList<GlycaemicIndexItem>) results.values;
notifyDataSetChanged();
clear();
//Add the items back in
for (Iterator iterator = localItems.iterator(); iterator
.hasNext();) {
GlycaemicIndexItem gi = (GlycaemicIndexItem) iterator.next();
add(gi);
}
}//end synchronized
}
}
}
}