How to filter a ListView using getFilter () in BaseAdapter

In my application, I created a custom list view, and I want to implement a filter so that the list can be filtered according to the text entered in EditText. I use BaseAdapter as a separate class, and I call this class in my main activity. I also implemented addTextChangedListener () in my main activity, and I also implemented getFilter () in my BaseAdapter class. But I do not know how to use getFilter () and filter my list accordingly. In the list, I am adding values ​​from the JSON URL. Please help me tell me how I can use getFilter () to filter my list.

Activity class code:

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); lv = (ListView)findViewById(R.id.listView1); et1 = (EditText)findViewById(R.id.editText1); inflator = getLayoutInflater(); et1.addTextChangedListener(this); JsonParser jParser = new JsonParser(); JSONObject json = jParser.getJSONfromUrl(url); try { JSONArray explore = json.getJSONArray("explore"); for(int i=0; i<explore.length(); i++) { JSONObject exp = explore.getJSONObject(i); list.add(exp.getString("username")); } } catch(JSONException e) { e.printStackTrace(); } srchadptr = new SearchAdapter(this, inflator, list); lv.setAdapter(srchadptr); } public void afterTextChanged(Editable s) { // TODO Auto-generated method stub srchadptr.getFilter().filter(s); } public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub } 

BaseAdapter class code:

 public class SearchAdapter extends BaseAdapter implements Filterable { Context context; LayoutInflater inflater; Button btn; View vw; ArrayList<String> list = new ArrayList<String>(); public SearchAdapter(Context context, LayoutInflater inflater, ArrayList<String> list) { // TODO Auto-generated constructor stub this.context = context; this.inflater = inflater; this.list = list; } /*public CharSequence filter(CharSequence cs) { return cs; }*/ public int getCount() { // TODO Auto-generated method stub return list.size(); } public Object getItem(int position) { // TODO Auto-generated method stub return position; } public long getItemId(int position) { // TODO Auto-generated method stub return position; } public View getView(final int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub LinearLayout ll = (LinearLayout) vw; final EditText edt = ((EditText)ll.getChildAt(0)); vw = inflater.inflate(R.layout.list_items, null); ImageView img = (ImageView)vw.findViewById(R.id.imageView1); TextView tv = (TextView)vw.findViewById(R.id.textView1); btn = (Button)vw.findViewById(R.id.button1); tv.setText(String.valueOf(list.get(position))); btn.setText(String.valueOf(list.get(position))); btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(context, list.get(position), Toast.LENGTH_LONG).show(); } }); return vw; } public android.widget.Filter getFilter() { // TODO Auto-generated method stub return new android.widget.Filter() { @Override protected void publishResults(CharSequence constraint, FilterResults results) { // TODO Auto-generated method stub } @Override protected FilterResults performFiltering(CharSequence constraint) { // TODO Auto-generated method stub return null; } }; } } 

Thanks in advance...

+4
source share
3 answers

Hope this example helps you

in Main_Activity

  EditText etSearch; BaseAdapterFilterable adapter; etSearch.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Listview name of the class Listview.this.adapter.getFilter().filter(s); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub } }); 

in your adapter puts this class in the getfilter method

 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(); } } 

also in your instance of adapter return from filter_here class

 @Override public Filter getFilter() { // TODO Auto-generated method stub return filter; } 
+9
source

In your base adapter, save two copies of the list, one original and one filtered. And change all the links in your BaseAdapter , to use only the filtered list.

1), activate the filter on the ListView : lv.setTextFilterEnabled (true);

2) in your TextWatcher, enable the filter in your srchadptr.getFilter () list. filter (s)

3) Update the base adapter to save two copies of the data, and replace the links to the filter list instead of the original list.

 public class SearchAdapter extends BaseAdapter implements Filterable { List<String> list = new ArrayList<String>(); List<String> listFiltered = new ArrayList<String>(); public SearchAdapter(Context context, ArrayList<String> list) { this.context = context; this.inflater = LayoutInflater.from(context) this.list = list; this.listFiltered=list; } public int getCount() { return listFiltered.size();//note the change } public Object getItem(int position) { return listFiltered.get(position);//note the change } //only altered lines shown in this function (change ``list`` to ``listFiltered``) public View getView(final int position, View convertView, ViewGroup parent) { tv.setText(String.valueOf(listFiltered.get(position))); btn.setText(String.valueOf(listFiltered.get(position))); btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(context, listFiltered.get(position), Toast.LENGTH_LONG).show(); } }); } //now write your filter function @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); if (constraint == null || constraint.length() == 0) { //no constraint given, just return all the data. (no search) results.count = list.size(); results.values = list; } else {//do the search List<String> resultsData = new ArrayList<>(); String searchStr = constraint.toString().toUpperCase(); for (String s : list) 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) { listFiltered = (ArrayList<String>) results.values; notifyDataSetChanged(); } }; } 
+2
source

I believe that working with filters is not so convenient .. How do I do this:

  ((EditText)findViewById(R.id.etSearch)).addTextChangedListener(new TextWatcher(){ private boolean mCountIncreased; @Override public void afterTextChanged(Editable s) { if (s.toString().length() == 0){ mDisplayedList.clear(); mDisplayedList.addAll(mFullList); mListAdapter.notifyDataSetChanged(); return; } if (mCountIncreased){ mDisplayedList.clear(); mDisplayedList.addAll(mFullList); } List<Item> toRemove = new ArrayList<Item>(); for (Item item : mDisplayedList){ if (someCondition) toRemove.add(currency); } } mDisplayedList.removeAll(toRemove); mListAdapter.notifyDataSetChanged(); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { mCountIncreased = after <= count; } @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} }); } 

Please note that you will have to change the adapter to work with mDisplayedList instead of mFullList .. and that it is.

This can lead to some overhead when your list contains multiple entries. But I worked with this list of + -300 elements, and I did not notice anything.

Hope this helps, Vlad

0
source

Source: https://habr.com/ru/post/894040/


All Articles