可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to implement a getFilter() on a base adapter to filter out search results on a List. Is there any example of how to implement a getFilter()?
MainActivity.java
final AppInfoAdapter adapter = new AppInfoAdapter(this, Utilities.getSystemFilteredApplication(this), getPackageManager());
public void onTextChanged(CharSequence s, int start, int before,
int count) {
adapter.getFilter().filter(s); //Filter from my adapter
adapter.notifyDataSetChanged(); //Update my view
}
AppInfoAdapter.java
package com.example.permission;
import java.util.List;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
public class AppInfoAdapter extends BaseAdapter implements Filterable{
private Context mContext;
private List mListAppInfo;
PackageManager mPackManager;
public AppInfoAdapter(Context c, List list, PackageManager pm) {
mContext = c;
mListAppInfo = list;
mPackManager = pm;
}
public int getCount() {
return mListAppInfo.size();
}
public Object getItem(int position) {
return mListAppInfo.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// get the selected entry
ApplicationInfo entry = (ApplicationInfo) mListAppInfo.get(position);
// reference to convertView
View v = convertView;
// inflate new layout if null
if(v == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
v = inflater.inflate(R.layout.layout_appinfo, null);
}
// load controls from layout resources
ImageView ivAppIcon = (ImageView)v.findViewById(R.id.ivIcon);
TextView tvAppName = (TextView)v.findViewById(R.id.tvName);
TextView tvPkgName = (TextView)v.findViewById(R.id.tvPack);
// set data to display
ivAppIcon.setImageDrawable(entry.loadIcon(mPackManager));
tvAppName.setText(entry.loadLabel(mPackManager));
tvPkgName.setText(entry.packageName);
// return view
return v;
}
public Filter getFilter() {
// TODO Auto-generated method stub
return null;
}
}
EDIT: Edited the code and added full AppInfoAdapter.java
回答1:
in your adapter put this class to use it in getfilter method
//this is a simple class that filtering the ArrayList of strings used in adapter
public class filter_here extends Filter{
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// TODO Auto-generated method stub
FilterResults Result = new FilterResults();
// if constraint is empty return the original names
if(constraint.length() == 0 ){
Result.values = Original_Names;
Result.count = Original_Names.size();
return Result;
}
ArrayList<String> Filtered_Names = new ArrayList<String>();
String filterString = constraint.toString().toLowerCase();
String filterableString;
for(int i = 0; i<Original_Names.size(); i++){
filterableString = Original_Names.get(i);
if(filterableString.toLowerCase().contains(filterString)){
Filtered_Names.add(filterableString);
}
}
Result.values = Filtered_Names;
Result.count = Filtered_Names.size();
return Result;
}
@Override
protected void publishResults(CharSequence constraint,FilterResults results) {
// TODO Auto-generated method stub
Names = (ArrayList<String>) results.values;
notifyDataSetChanged();
}
}
return instance from it in getfilter
@Override
public Filter getFilter() {
// TODO Auto-generated method stub
return filter;
}
full example
回答2:
this almost got me killed :)
- implement your BaseAdapter like this:
define an ArrayList of List in your public adapter class which is gonna contain temporary items of your Original List.
public class MyAdapter extends BaseAdapter implements Filterable{
public static ArrayList<String> temporarylist;
public static ArrayList<String> OriginalList;
private Activity activity;
public MyAdapter(Activity activity, ArrayList<String> OriginalList) {
super();
this.activity=activity;
this.OriginalList = OriginalList;
temporarylist=OriginalList;
}
.
.
.
create getFilter() method with the following code[as an example]:
public Filter getFilter() {
Filter filter = new Filter() {
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
temporarylist=(ArrayList<String>)results.values;
notifyDataSetChanged();
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
ArrayList<String> FilteredList= new ArrayList<String>();
if (constraint == null || constraint.length() == 0) {
// No filter implemented we return all the list
results.values = OriginalList;
results.count = OriginalList.size();
}
else {
for (int i = 0; i < OriginalList.size(); i++) {
String data = OriginalList.get(i);
if (data.toLowerCase().contains(constraint.toString())) {
FilteredList.add(data);
}
}
results.values = FilteredList;
results.count = FilteredList.size();
}
return results;
}
};
return filter;
}
And finally in your activity for your EditText:
MyAdapter adapter;
ArrayList<String> items;
ListView list = (ListView) findViewById(R.id.list);
items = new ArrayList<String>();
for (int i=0;i<30;i++){
items.add("Hello world "+String.valueof(i));
}
adapter = new GameAdapter(this, items);
list.setAdapter(adapter);
EditText inputSearch = (EditText) findViewById(R.id.Search_txt);
inputSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
MyActivity.this.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
}
});
回答3:
You need to return an instance of a Filter
. To write a filter, subclass Filter
and implement performFiltering
and publishResults
. See the docs.
回答4:
Can you post your full AppInfoAdapter
? Also is there any reason extending from BaseAdapter
and not ArrayAdapter
? If you have an ArrayList
of objects, use ArrayAdapter
, it already implements Filterable
interface.
Actually you are using a List
, your adapter can be rewritten to extends ArrayAdapter
which already is Filterable
.
public class AppInfoAdapter extends ArrayAdapter<ApplicationInfo> {
private Context mContext;
PackageManager mPackManager;
public AppInfoAdapter(Context c, List<ApplicationInfo> list, PackageManager pm) {
super(c, 0, new ArrayList<ApplicationInfo>());
mContext = c;
mPackManager = pm;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// get the selected entry
ApplicationInfo entry = (ApplicationInfo) getItem(position);
// reference to convertView
View v = convertView;
// inflate new layout if null
if(v == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
v = inflater.inflate(R.layout.layout_appinfo, null);
}
// load controls from layout resources
ImageView ivAppIcon = (ImageView)v.findViewById(R.id.ivIcon);
TextView tvAppName = (TextView)v.findViewById(R.id.tvName);
TextView tvPkgName = (TextView)v.findViewById(R.id.tvPack);
// set data to display
ivAppIcon.setImageDrawable(entry.loadIcon(mPackManager));
tvAppName.setText(entry.loadLabel(mPackManager));
tvPkgName.setText(entry.packageName);
// return view
return v;
}
}
回答5:
General procedure
- Enable text filtering on your ListView
- Change your baseadapter to store two copies of the list, one original, one filtered.
- Change all access references in your BaseAdapter to refer to the Filtered list, not the original.
- Implement your Filter function in BaseAdapter.
Step 1:
listview.setTextFilterEnabled(true);
Step 2:
public class AppInfoAdapter extends BaseAdapter implements Filterable{
private List mListAppInfo;
private List mListAppInfoFiltered;
public AppInfoAdapter(Context c, List list, PackageManager pm) {
mContext = c;
mListAppInfo = list;
mPackManager = pm;
mPackManagerFiltered = pm; //added line
}
Step 3:
public int getCount() {
return mListAppInfoFiltered.size();
}
public Object getItem(int position) {
return mListAppInfoFiltered.get(position);
}
public View getView(int position, View convertView, ViewGroup parent) {
// get the selected entry
ApplicationInfo entry = (ApplicationInfo) mListAppInfoFiltered.get(position);
}
Step 4:
I am not sure what type your list is, so assuming a list of String:
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
//no search, so just return all the data
results.count = mListAppInfo.size();
results.values = mListAppInfo;
} else {//do the search
List<String> resultsData = new ArrayList<>();
String searchStr = constraint.toString().toUpperCase();
for (String s : mListAppInfo)
if (s.toUpperCase().contains(searchStr)) resultsData.add(s);
results.count = resultsData.size();
results.values = resultsData;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mListAppInfoFiltered = (ArrayList<MyObject>) results.values;
notifyDataSetChanged();
}
};
}
}
回答6:
getFilter() can be override in adapters and return the filter object which contains filtered list . There are two key methods in Filter() class; performFiltering and publishResults. The first method performs the filtering in worker thread and the later one return filtered list of objects.
You can refer to sample code below
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// TODO Auto-generated method stub
if (results.count == 0) {
notifyDataSetInvalidated();
}else{
mListAppInfo = (ArrayList<SampleItem>) results.values;
notifyDataSetChanged();
}
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// TODO Auto-generated method stub
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
results.values = mListAppInfo;
results.count = mListAppInfo.size();
}else{
ArrayList<SampleItem> filter_items = new ArrayList<>();
for (SampleItem item : mListAppInfo) {
if (item.getItemName().toLowerCase().startsWith(constraint.toString().toLowerCase())) {
filter_items.add(item);
}
}
results.values = filter_items ;
results.count = filter_items.size();
}
return results;
}
};
}
Hope you find it useful .
回答7:
extend your class with ArrayAdapter,then override methods,and create object of filter class and return with it.