android中自定义ArrayAdapter中的自定义getFilter
Posted
技术标签:
【中文标题】android中自定义ArrayAdapter中的自定义getFilter【英文标题】:Custom getFilter in custom ArrayAdapter in android 【发布时间】:2013-10-08 00:08:53 【问题描述】:我在自定义 arrayAdapter 中实现自定义 getFilter 时遇到问题。其实我不知道如何实现它。尝试了各种代码,但仍然没有运气。这是我的自定义数组适配器。
package com.test.FilterableList.Adapters;
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.test.FilterableList.Models.ListTO;
import com.test.FilterableList.R;
import android.widget.Filterable;
public class FilterableAdapter extends ArrayAdapter<ListTO> implements Filterable
// declaring our ArrayList of items
public ArrayList<ListTO> objects;
/* here we must override the constructor for ArrayAdapter
* the only variable we care about now is ArrayList<Item> objects,
* because it is the list of objects we want to display.
*/
public FilterableAdapter(Context context, int textViewResourceId, ArrayList<ListTO> objects)
super(context, textViewResourceId, objects);
this.objects = objects;
/*
* we are overriding the getView method here - this is what defines how each
* list item will look.
*/
public View getView(int position, View convertView, ViewGroup parent)
// assign the view we are converting to a local variable
View v = convertView;
// first check to see if the view is null. if so, we have to inflate it.
// to inflate it basically means to render, or show, the view.
if (v == null)
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.list_item, null);
/*
* Recall that the variable position is sent in as an argument to this method.
* The variable simply refers to the position of the current object in the list. (The ArrayAdapter
* iterates through the list we sent it)
*
* Therefore, i refers to the current Item object.
*/
ListTO i = objects.get(position);
if (i != null)
// This is how you obtain a reference to the TextViews.
// These TextViews are created in the XML files we defined.
TextView tt = (TextView) v.findViewById(R.id.list_name);
if (tt != null)
tt.setText(i.FileName);
// the view must be returned to our activity
return v;
这是 ListTO 类。
package com.test.FilterableList.Models;
public class ListTO
public int Id;
public String FileName;
public String FileUri;
public ListTO(int id, String fileName, String fileUri)
Id = id;
FileName = fileName;
FileUri = fileUri;
这是布局。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:orientation="vertical"
android:background="@drawable/blacklikenbackground"
tools:context=".AllListActivity" >
<EditText
android:layout_
android:layout_
android:text="Search"
android:id="@+id/inputSearch"
/>
<ListView
android:id="@+id/test_list"
android:layout_
android:layout_>
</ListView>
</LinearLayout>
这里的搜索关键字来自“inputSearch”EditText。
这是文本更改的侦听器。
inputSearch.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3)
// When user changed the Text
// Toast.makeText(getActivity(), cs.toString(), Toast.LENGTH_LONG).show();
m_adapter.getFilter().filter(cs);
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3)
// TODO Auto-generated method stub
@Override
public void afterTextChanged(Editable arg0)
// TODO Auto-generated method stub
);
谢谢。
【问题讨论】:
您到底想达到什么目标?过滤器数据将来自哪里,您希望过滤器做什么? 我还建议您看看这个出色的答案:***.com/a/14369336/72746 - 这可能就是您要找的。span> @Axarydax 抱歉,布局已添加到问题中。实际上 Search 关键字来自“inputSearch”EditText。我想实现谷歌中使用的自动建议功能;但是从列表视图来看。 ArrayAdapter 抽象了所有这些功能,您只需要覆盖 ListTO 上的 toString()。查看它的实现grepcode.com/file/repository.grepcode.com/java/ext/…@chandu tangudu 答案是正确的 【参考方案1】:您遇到了问题,主要是因为您使用的是自定义对象。如果您将 String 或 int 值传递给数组适配器,它知道如何过滤它。但是,如果您通过自定义对象默认过滤器实现,则不知道如何处理。
虽然尚不清楚您要在过滤器中执行什么操作,但我建议您按照以下步骤操作。
-
正确实现
ListTO
,尽管它与您现在的目标无关
实现自定义过滤器
归还您的过滤器
实现自定义过滤器
您要做的第一件事是,来自阵列适配器的implements
Filterable
。
其次,提供你的Filter
的实现
Filter myFilter = new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
FilterResults filterResults = new FilterResults();
ArrayList<ListTO> tempList=new ArrayList<ListTO>();
//constraint is the result from text you want to filter against.
//objects is your data set you will filter from
if(constraint != null && objects!=null)
int length=objects.size();
int i=0;
while(i<length)
ListTO item=objects.get(i);
//do whatever you wanna do here
//adding result set output array
tempList.add(item);
i++;
//following two lines is very important
//as publish result can only take FilterResults objects
filterResults.values = tempList;
filterResults.count = tempList.size();
return filterResults;
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence contraint, FilterResults results)
objects = (ArrayList<ListTO>) results.values;
if (results.count > 0)
notifyDataSetChanged();
else
notifyDataSetInvalidated();
;
最后一步,
@Override
public Filter getFilter()
return myFilter;
【讨论】:
您能帮我解决我的问题吗:***.com/questions/20524417/…。我遵循了该方法,但 ListView 就消失了。 @minhaz 我已经实现了您的解决方案并且效果很好,但是我遇到了一个问题,如果我搜索一个字符串然后将空格返回到空,它不会显示所有数组项. 我也面临同样的问题,当我退格时没有任何效果。 @minhaz 我不明白的一件事是您在publishResults
中重新分配objects
,因此您丢失了原始列表??
这样做:- if (searchquery.length()
【参考方案2】:
无需编写数组适配器。编写一个 toString() 方法,它应该返回文件名的值。
喜欢
public class ListTO
public int Id;
public String FileName;
public String FileUri;
public ListTO(int id, String fileName, String fileUri)
Id = id;
FileName = fileName;
FileUri = fileUri;
public String toString()
return FileName
【讨论】:
如果您只需要基本搜索,这是一个很棒且简单的解决方案。 +1 这不仅仅是伟大的,这是不重新发明***的正确答案 非常适合实现简单搜索【参考方案3】:您需要覆盖 Adapter 中的 getFilter()
方法并提供您自己的过滤器。
看看这个Filterable Example 看看实际的实现。
将以下getFilter()
代码添加到您的FilterableAdapter
类中,并用您的过滤器填充它:
/* (non-Javadoc)
* @see android.widget.ArrayAdapter#getFilter()
*/
@Override
public Filter getFilter()
return new Filter()
/* (non-Javadoc)
* @see android.widget.Filter#performFiltering(java.lang.CharSequence)
*/
@Override
protected FilterResults performFiltering(CharSequence constraint)
// TODO Auto-generated method stub
/*
* Here, you take the constraint and let it run against the array
* You return the result in the object of FilterResults in a form
* you can read later in publichResults.
*/
return null;
/* (non-Javadoc)
* @see android.widget.Filter#publishResults(java.lang.CharSequence, android.widget.Filter.FilterResults)
*/
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
// TODO Auto-generated method stub
/*
* Here, you take the result, put it into Adapters array
* and inform about the the change in data.
*/
;
我在 cmets 中添加了提示。
【讨论】:
【参考方案4】:试试这个:
public class Adptr extends BaseAdapter implements Filterable
public ArrayList<Model> modelValues;
private Activity activity;
private LayoutInflater layoutinflater;
private List<Model> mOriginalValues;
private int PositionSelected = 0;
public Adptr (ArrayList<Model> modelValues, Activity activity)
super();
this.modelValues = modelValues;
this.activity = activity;
@Override
public int getCount()
return modelValues.size();
@Override
public Object getItem(int position)
return modelValues.get(position);
@Override
public long getItemId(int position)
return position;
@Override
public View getView(final int position, View convertView, ViewGroup parent)
layoutinflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewHolder holder = null;
Model model = modelValues.get(position);
if (convertView == null || !(convertView.getTag() instanceof ViewHolder))
convertView = layoutinflater.inflate(R.layout.row_search, null);
holder = new ViewHolder();
holder.txtName = (TextView) convertView.findViewById(R.id.row_serch_txt_name);
convertView.setTag(holder);
convertView.setTag(R.id.row_serch_txt_name, holder.txtName);
else
holder = (ViewHolder) convertView.getTag();
holder.txtArtistName.setText("" + modelValue.get_NAME());
return convertView;
class ViewHolder
TextView txtName;
@Override
public Filter getFilter()
Filter filter = new Filter()
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
modelValues = (ArrayList<ModelValueArtist>) results.values; // has
notifyDataSetChanged();
@Override
protected FilterResults performFiltering(CharSequence constraint)
FilterResults results = new FilterResults(); // Holds the
// results of a
// filtering
// operation in
// values
// List<String> FilteredArrList = new ArrayList<String>();
List<Model> FilteredArrList = new ArrayList<Model>();
if (mOriginalValues == null)
mOriginalValues = new ArrayList<Model>(modelValues); // saves
/********
*
* If constraint(CharSequence that is received) is null returns
* the mOriginalValues(Original) values else does the Filtering
* and returns FilteredArrList(Filtered)
*
********/
if (constraint == null || constraint.length() == 0)
// set the Original result to return
results.count = mOriginalValues.size();
results.values = mOriginalValues;
else
Locale locale = Locale.getDefault();
constraint = constraint.toString().toLowerCase(locale);
for (int i = 0; i < mOriginalValues.size(); i++)
Model model = mOriginalValues.get(i);
String data = model.get_NAME();
if (data.toLowerCase(locale).contains(constraint.toString()))
FilteredArrList.add(modelMyMall);
// set the Filtered result to return
results.count = FilteredArrList.size();
results.values = FilteredArrList;
return results;
;
return filter;
【讨论】:
我一个字一个字地用这个词,但没有用。建议覆盖ArrayAdapter
中的getCount()
,它只是过滤结果数量而不是结果本身。我在publishResults()
中结束了mThis.clear();mThis.addAll(customList);
【参考方案5】:
您可以在自定义对象类中覆盖 toString() 并返回要过滤掉的 String 对象。
@Override
public void toString()
return this.toBeFilteredString;
然后简单地使用arrayAdapter的默认内置过滤器并使用它调用它
adapter.getFilter().filter(Charsequence c);
【讨论】:
正是我想要的! :) 那里也一样!在编写了公认的解决方案后,我寻找了像这样更简单的东西......谢谢!【参考方案6】:我在 SO 上搜索了很多答案以获得所需的所有 sn-ps。所以这是我的班级Registration
的自定义过滤器的 Kotlin 版本。
这个确实有效,您需要的所有信息都在此代码中。
class RegistrationArrayAdapter(context: Context, private val layoutResId: Int, registrations: List<Registration>) :
ArrayAdapter<Registration>(context, layoutResId, registrations)
private val filter = RegistrationFilter(registrations)
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View
val registration = getItem(position)
val view = convertView ?: LayoutInflater.from(context).inflate(layoutResId, null)
(view as TextView).text = registration?.mainGuest?.name ?: ""
return view
override fun getFilter() = filter
inner class RegistrationFilter(private val originalList: List<Registration>) : Filter()
private val sourceObjects: ArrayList<Registration> = ArrayList()
init
synchronized (this)
sourceObjects.addAll(originalList)
override fun performFiltering(constraint: CharSequence?): FilterResults
if (constraint == null) return FilterResults()
val result = FilterResults()
if (constraint.isNotEmpty())
val filteredList = ArrayList<Registration>()
sourceObjects.filterTo(filteredList) isWithinConstraint(it, constraint)
result.count = filteredList.size
result.values = filteredList
else
synchronized(this)
result.values = sourceObjects
result.count = sourceObjects.size
return result
override fun publishResults(constraint: CharSequence?, results: FilterResults)
if (results.values == null) return
@Suppress("UNCHECKED_CAST")
val filtered = results.values as ArrayList<Registration>
if (results.count > 0)
clear()
addAll(filtered)
notifyDataSetChanged()
else
notifyDataSetInvalidated()
override fun convertResultToString(resultValue: Any?): CharSequence
return (resultValue as Registration).mainGuest.name
private fun isWithinConstraint(registration: Registration, constraint: CharSequence): Boolean
return registration.mainGuest.name.toLowerCase().contains(constraint, true)
【讨论】:
你是唯一的救星!!没有其他解决方案可以像您那样工作。【参考方案7】:正如你所说“我想实现类似谷歌中使用的自动建议功能;但这里是从列表视图中。-重做”
还有另一种方法可以使用 自动完成文本视图
更多详情请通过AutoCompleteTextView
OutPut 将如下所示
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/listitem_layout"
android:layout_
android:layout_
android:background="#e2e2e2"
android:orientation="vertical" >
<AutoCompleteTextView
android:id="@+id/autocomplete"
android:layout_
android:layout_
android:layout_margin="10dp"
android:background="@drawable/text_area"
android:inputType="text|textNoSuggestions|textMultiLine"
android:paddingLeft="10dp"
android:popupBackground="#EFEEEC"
android:textColor="#333333"
android:textColorHint="#9c9c9c"
android:textSize="18sp"
android:completionThreshold="1" />
</LinearLayout>
auto_textview.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:padding="12dp"
android:textColor="#333333"
android:layout_margin="15dp"
android:textSize="16sp" >
</TextView>
MainActivity.java
public class MainActivity extends Activity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AutoCompleteTextView seachView = (AutoCompleteTextView) findViewById(R.id.autocomplete);
seachView.setAdapter(new ArrayAdapter<String>(this,
R.layout.auto_textview, getHeading()));
/**
* @return
*/
public List<String> getHeading()
List<String> list = new ArrayList<String>();
list.add("Android");
list.add("Arnold");
list.add("Blackberry");
list.add("Blackpearl");
list.add("Country");
list.add("Canada");
list.add("City");
list.add("Street Address");
list.add("Objective C");
return list;
希望这会对你有所帮助。
【讨论】:
你能帮我解决我的问题吗:***.com/questions/20524417/…以上是关于android中自定义ArrayAdapter中的自定义getFilter的主要内容,如果未能解决你的问题,请参考以下文章
在AutocompleteTextview的下拉列表中自定义分隔符/分隔符
Android - ListView 中的 EditTexts 绑定到自定义 ArrayAdapter - 跟踪更改
使用android中的自定义arrayadapter在listview中使用复选框检查后如何删除多个项目?