天道酬勤,学无止境

Filtering ListView with custom (object) adapter

I'm trying to implement filtering of a ListView which is uses a custom object adapter, but I can't find any useful samples. The included code is very simplified, so no- keep in mind I can't use an regular ArrayAdapter. I have a EditText above the ListView, and when the user enters text in the EditText widget I would like to filter the ListView by the text written in the EditText. Any suggestions would be much appreciated!

Here is the snippet from the activity class:

public class management_objects extends Activity {

private static List<User> UserList;
private EfficientAdapter adapter = null;
private ListView objectListView = null;
private EditText SearchText = null;

private static class EfficientAdapter extends BaseAdapter implements Filterable{
    private LayoutInflater mInflater;   

    public EfficientAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
    }

    public int getCount() {
        return UserList.size();
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder; 
        if (convertView == null) { 
            convertView = mInflater.inflate(R.layout.imagelayout_2lines, null);
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.managementObjectText);
            holder.subtext = (TextView) convertView.findViewById(R.id.managementObjectSubText);
            holder.icon = (ImageView) convertView.findViewById(R.id.managementObjectIcon);
            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.text.setText(UserList.get(position).getFirstName());
        holder.subtext.setText(UserList.get(position).getLastName());
        holder.icon.setImageResource(R.drawable.user);

        return convertView;
    }

    static class ViewHolder { 
        TextView text;
        TextView subtext;
        ImageView icon;
    }

    @Override
    public Filter getFilter() {
        return null;
    }
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.adobjectlist);
    Bundle extras = getIntent().getExtras();

    SearchText = (EditText) findViewById(R.id.SearchBox);    
    SearchText.addTextChangedListener(filterTextWatcher);

    objectListView = (ListView) findViewById(R.id.ObjectList);
    objectListView.setOnItemClickListener(Item_Click);
    adapter = new EfficientAdapter(this);
    ComputerName = extras.getString("COMPUTER_NAME");

    //Get User list from webservice
    ShowUsers();
}

Here is The User class:

 public class User {
  private int UserId;
  private String FirstName;
  private String LastName;

    public int getUserId() {
        return UserId;
    }
    public void setUserId(int UserId) {
        this.UserId = UserId;
    }
    public String getFirstName() {
        return FirstName;
    }
    public void setFirstName(String FirstName) {
        this.FirstName = FirstName;
    }
    public String getLastName() {
        return LastName;
    }
    public void setLastName(String LastName) {
        this.LastName = LastName;
    }
}

评论

You need to do a few things:

1) In your activity, register for a text change listener on your EditText that contains the value the user enters:

mSearchValue.addTextChangedListener(searchTextWatcher);

2) Create your searchTextWatcher and have it do something:

private TextWatcher searchTextWatcher = new TextWatcher() {
    @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // ignore
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // ignore
        }

        @Override
        public void afterTextChanged(Editable s) {
            Log.d(Constants.TAG, "*** Search value changed: " + s.toString());
            adapter.getFilter().filter(s.toString());
        }
    };

3) Override getFilter() in your custom adapter and have it filter the results and notify the listview that the dataset has changed.

    @Override
    public Filter getFilter() {
        return new Filter() {
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                Log.d(Constants.TAG, "**** PUBLISHING RESULTS for: " + constraint);
                myData = (List<MyDataType>) results.values;
                MyCustomAdapter.this.notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                Log.d(Constants.TAG, "**** PERFORM FILTERING for: " + constraint);
                List<MyDataType> filteredResults = getFilteredResults(constraint);

                FilterResults results = new FilterResults();
                results.values = filteredResults;

                return results;
            }
        };
    }

Here an interesting example

public Filter getFilter() {
    return new Filter() {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            final FilterResults oReturn = new FilterResults();
            final ArrayList<station> results = new ArrayList<station>();
            if (orig == null)
                orig = items;
            if (constraint != null) {
                if (orig != null && orig.size() > 0) {
                    for (final station g : orig) {
                        if (g.getName().toLowerCase()
                                .contains(constraint.toString()))
                            results.add(g);
                    }
                }
                oReturn.values = results;
            }
            return oReturn;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint,
                FilterResults results) {
            items = (ArrayList<station>) results.values;
            notifyDataSetChanged();
        }
    };
}

public void notifyDataSetChanged() {
    super.notifyDataSetChanged();
    notifyChanged = true;
}

For those who don't need the Filterable interface, there is a much simpler solution. This also handles notifyDataSetChanged() correctly where the other solutions fail. Note that you need to add a getArray() function to the BaseAdapter that just returns the array object that was passed to the constructor.

public abstract class BaseFilterAdapter<T> extends BaseAdapter<T> {

    private List<T> original;
    private String lastFilter;

    public BaseFilterAdapter(Context context, List<T> array) {
        super(context, new LinkedList<T>());
        original = array;
        filter("");
    }

    protected abstract Boolean predicate(T element, String filter);

    public void filter(String filter) {
        lastFilter = filter;
        super.getArray().clear();
        for (T element : original)
            if (predicate(element, filter))
                super.getArray().add(element);
        super.notifyDataSetChanged();
    }

    @Override
    public List<T> getArray() {
        return original;
    }

    @Override
    public void notifyDataSetChanged() {
        filter(lastFilter);
    }
}

Add toString override on your base class. For example

@Override
public String toString() {
    return this.name;
}

Above makes your List as string list. So you can use:

your_edit_text.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
        YourActivity.this.YourAdapter.getFilter().filter(arg0);
    }

    @Override
    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
    }

    @Override
    public void afterTextChanged(Editable arg0) {    
    }
});

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 使用ArrayAdapter在Android中进行自定义过滤(Custom filtering in Android using ArrayAdapter)
    问题 我正在尝试过滤使用此ArrayAdapter填充的ListView: package me.alxandr.android.mymir.adapters; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Set; import me.alxandr.android.mymir.R; import me.alxandr.android.mymir.model.Manga; import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Filter; import android.widget.SectionIndexer; import android.widget
  • 如何在Android的自定义列表视图中使用搜索功能(How to use search functionality in custom list view in Android)
    问题 我创建了一个具有多个项目的列表视图。 我还在上面创建了一个搜索框。 我想基于列表的特定字段来实现搜索功能。 我怎样才能做到这一点? 任何帮助将不胜感激。 回答1 您必须为此使用model,listview和customadapter进行过滤。 我已经为此创建了一个演示。 假设您有一个名为Product的模型,并且要在自定义列表视图中显示其内容,该列表的名称和价格将显示在文本视图中。 我的意思是在具有两个textview的自定义行中,并且您想按自定义行的字段之一过滤列表。 在这里,我用“名称”过滤 屏幕截图: 最初的 已过滤 源代码 模型 public class Product { public String name; public Integer price; public Product(String name, Integer price) { super(); this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getPrice() { return price; } public void setPrice
  • 具有自定义适配器的ListView中的SearchView(SearchView In ListView having a custom Adapter)
    问题 伙计们,我需要一些帮助。我一直在尝试在我的项目中实现SearchView。但是我的项目中包含一个带有附加自定义适配器的列表视图。我搜索了很多站点,但是所有示例都使用arrayadapter实现。让我们说我有一个Employee类,它包含名称和年龄字段。如何仅使用员工的姓名来过滤员工。 public class MainActivity extends Activity implements SearchView.OnQueryTextListener { SearchView mSearchView; ListView mListView; //String mStrings[]= {"abc","def","efg","ghi","ijk","apple","agxhsdgc","abbbcc"}; ArrayList<Employee> emp_list=null; EmployeeAdapter emp_adapter=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSearchView=(SearchView)
  • 由LoaderManager管理的具有自定义适配器的AlphabetIndexer(AlphabetIndexer with Custom Adapter managed by LoaderManager)
    问题 我正在尝试使用这样的自定义适配器实现AlphabetIndexer 带自定义适配器的AlphabetIndexer 我的类ContactsCursorAdapter扩展了SimpleCursorAdapter并实现了SectionIndexer并且我正在使用LoaderManager来管理适配器的光标,因此我像上面示例的第二个答案所示那样覆盖了swapCursor()方法。 public class ContactsCursorAdapter extends SimpleCursorAdapter implements SectionIndexer{ private LayoutInflater mInflater; private Context mContext; private AlphabetIndexer mAlphaIndexer; public ContactsCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { super(context, layout, c, from, to); mInflater = LayoutInflater.from(context); mContext = context; } public View getView
  • How to implement getfilter() with custom adapter that extends baseadapter
    here is my main activity package com.javacodegeeks.android.lbs; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.Toast; import lbs.promotion.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.http.NameValuePair; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import
  • 具有过滤器Android的自定义Listview适配器(Custom Listview Adapter with filter Android)
    问题 请尝试在我的列表视图上实施过滤器。 但是每当文本更改时,列表就会消失。请帮助这是我的代码。 适配器类。 package com.talagbe.schymn; 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; public class HymnsAdapter extends ArrayAdapter<Hymns> { ArrayList<Hymns> hymnarray; Context context; LayoutInflater inflater; int Resource; public HymnsAdapter(Context context, int resource, ArrayList<Hymns> objects) { super(context, resource, objects); // TODO Auto-generated constructor stub
  • AlphabetIndexer with Custom Adapter managed by LoaderManager
    I am trying to implement AlphabetIndexer with Custom Adapter like this AlphabetIndexer with Custom Adapter My class ContactsCursorAdapter extends SimpleCursorAdapter and implements SectionIndexer and I am using a LoaderManager to manage my adapter's cursor so i have overridden the swapCursor() method like the second answer to the example above indicates. public class ContactsCursorAdapter extends SimpleCursorAdapter implements SectionIndexer{ private LayoutInflater mInflater; private Context mContext; private AlphabetIndexer mAlphaIndexer; public ContactsCursorAdapter(Context context, int
  • ArrayIndexOutOfBoundsException with custom Android Adapter for multiple views in ListView
    I am attempting to create a custom Adapter for my ListView since each item in the list can have a different view (a link, toggle, or radio group), but when I try to run the Activity that uses the ListView I receive an error and the app stops. The application is targeted for the Android 1.6 platform. The code: public class MenuListAdapter extends BaseAdapter { private static final String LOG_KEY = MenuListAdapter.class.getSimpleName(); protected List<MenuItem> list; protected Context ctx; protected LayoutInflater inflater; public MenuListAdapter(Context context, List<MenuItem> objects) { this
  • Custom filtering in Android using ArrayAdapter
    I'm trying to filter my ListView which is populated with this ArrayAdapter: package me.alxandr.android.mymir.adapters; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Set; import me.alxandr.android.mymir.R; import me.alxandr.android.mymir.model.Manga; import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Filter; import android.widget
  • Android中自定义ArrayAdapter中的自定义getFilter(Custom getFilter in custom ArrayAdapter in android)
    问题 我在自定义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
  • Custom Listview Adapter with filter Android
    Please am trying to implement a filter on my listview. But whenever the text change, the list disappears.Please Help Here are my codes. The adapter class. package com.talagbe.schymn; 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; public class HymnsAdapter extends ArrayAdapter<Hymns> { ArrayList<Hymns> hymnarray; Context context; LayoutInflater inflater; int Resource; public HymnsAdapter(Context context, int resource
  • notifyDataSetChange在自定义适配器上不起作用(notifyDataSetChange not working from custom adapter)
    问题 重新填充ListView ,我从Adapter调用特定方法。 问题: 当我从Adapter调用updateReceiptsList ,数据会刷新,但ListView不能反映更改。 问题: 为什么在调用notifyDataSetChanged时ListView显示新数据? 适配器: public class ReceiptListAdapter extends BaseAdapter { public List<Receipt> receiptlist; private Context context; private LayoutInflater inflater; private DateHelpers dateH; public ReceiptListAdapter(Activity activity, Context mcontext, List<Receipt> rl) { context = mcontext; receiptlist = rl; Collections.reverse(receiptlist); inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); dateH = new DateHelpers(); } @Override
  • how to use an ArrayAdapter in android of custom objects
    How can I use the properties of a custom object in a Listview. If I implement an ArrayAdapter with a list of Strings it displays fine in Listview but when I use a list of custom objects, it just outputs the memory address. The code I have up to now: ArrayList<CustomObject> allObjects = new ArrayList<>(); allObjects.add("title", "http://url.com")); ArrayAdapter<NewsObject> adapter = new ArrayAdapter<NewsObject>(this, android.R.layout.simple_list_item_1, android.R.id.text1, allNews); // Assign adapter to ListView listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView
  • SearchView In ListView having a custom Adapter
    Guys I am in need of some help.I have been trying to implement a SearchView in my project.But my project contains a listview with a custom adapter attached to it..I have searched many sites but all have examples implemented using an arrayadapter..Lets say I have an Employee class and it contains name and age fields..How to I filter the employees using their Name only.. public class MainActivity extends Activity implements SearchView.OnQueryTextListener { SearchView mSearchView; ListView mListView; //String mStrings[]= {"abc","def","efg","ghi","ijk","apple","agxhsdgc","abbbcc"}; ArrayList
  • Android AutoCompleteTextView with Custom Adapter filtering not working
    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
  • 列表视图过滤器Android(List View Filter Android)
    问题 我在android中创建了一个列表视图,我想在列表上方添加编辑文本,当用户输入文本时,该列表将根据用户输入进行过滤 谁能告诉我是否有办法在android中过滤列表适配器? 回答1 在列表视图顶部的.xml布局文件中添加一个EditText。 并且在您的活动/片段中。 lv = (ListView) findViewById(R.id.list_view); inputSearch = (EditText) findViewById(R.id.inputSearch); // Adding items to listview adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.product_name, products); lv.setAdapter(adapter); inputSearch.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) { // When user changed the Text MainActivity.this.adapter.getFilter().filter(cs
  • 自定义适配器的getView()方法未调用(Custom Adapter getView() method is not called)
    问题 这是我在列表中设置自定义适配器的片段的代码。 没有错误,但ListView为空。 我已经实现了getCount() ,它可以在ArrayList中返回正确数量的项目。 我在logcat ("Inside", "GetView")不到("Inside", "GetView") 分段 public class ServiceCarListFragment extends Fragment { private String url; private ArrayList<CarDetail> carDetailList = new ArrayList<CarDetail>(); private CarListAdapter adapter; private ListView mList; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); url = getActivity().getIntent().getStringExtra("url"); new DownloadCarDetail().execute(url); } @Override public View
  • Custom Filtering ArrayAdapter in ListView
    I am a begginer in Android but I tried to make a custom listview filtering and I it worked somehow. The only problem I have is that the ArrayList that I kept all the values ( "original" ArrayList ) , is getting lower and lower on items in every filtering. I can't explain this but I thought that you can help me somehow . Anyway here is the Custom ArrayAdaptor : public class PkmnAdapter extends ArrayAdapter<Pkmn> { private ArrayList<Pkmn> original; private ArrayList<Pkmn> fitems; private Filter filter; public PkmnAdapter(Context context, int textViewResourceId, ArrayList<Pkmn> items) { super
  • Android custom Row Item for ListView(Android custom Row Item for ListView)
    问题 我有一个ListView,其行中应具有以下布局: HEADER Text HEADER应该是静态的,但是Text每隔几秒钟就会更改一次。 我通过填充String[] array实现它,将其传递给ArrayAdapter并在每次数据更改时对其进行设置: data_array = populateString(); adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, data_array); listView.setAdapter(adapter); 我的问题是我不知道如何以上述格式显示数据。 提前致谢。 回答1 将此row.xml添加到您的布局文件夹 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout
  • notifyDataSetChange not working from custom adapter
    When I repopulate my ListView, I call a specific method from my Adapter. Problem: When I call updateReceiptsList from my Adapter, the data is refreshed, but my ListView doesn't reflect the change. Question: Why doesn't my ListView show the new data when I call notifyDataSetChanged? Adapter: public class ReceiptListAdapter extends BaseAdapter { public List<Receipt> receiptlist; private Context context; private LayoutInflater inflater; private DateHelpers dateH; public ReceiptListAdapter(Activity activity, Context mcontext, List<Receipt> rl) { context = mcontext; receiptlist = rl; Collections