Custom Listview Adapter with filter Android

后端 未结 10 696
北荒
北荒 2020-11-22 06:07

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.

p         


        
相关标签:
10条回答
  • 2020-11-22 06:59

    You can use the Filterable interface on your Adapter, have a look at the example below:

    public class SearchableAdapter extends BaseAdapter implements Filterable {
        
        private List<String>originalData = null;
        private List<String>filteredData = null;
        private LayoutInflater mInflater;
        private ItemFilter mFilter = new ItemFilter();
        
        public SearchableAdapter(Context context, List<String> data) {
            this.filteredData = data ;
            this.originalData = data ;
            mInflater = LayoutInflater.from(context);
        }
     
        public int getCount() {
            return filteredData.size();
        }
     
        public Object getItem(int position) {
            return filteredData.get(position);
        }
     
        public long getItemId(int position) {
            return position;
        }
     
        public View getView(int position, View convertView, ViewGroup parent) {
            // A ViewHolder keeps references to children views to avoid unnecessary calls
            // to findViewById() on each row.
            ViewHolder holder;
     
            // When convertView is not null, we can reuse it directly, there is no need
            // to reinflate it. We only inflate a new View when the convertView supplied
            // by ListView is null.
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.list_item, null);
     
                // Creates a ViewHolder and store references to the two children views
                // we want to bind data to.
                holder = new ViewHolder();
                holder.text = (TextView) convertView.findViewById(R.id.list_view);
     
                // Bind the data efficiently with the holder.
     
                convertView.setTag(holder);
            } else {
                // Get the ViewHolder back to get fast access to the TextView
                // and the ImageView.
                holder = (ViewHolder) convertView.getTag();
            }
     
            // If weren't re-ordering this you could rely on what you set last time
            holder.text.setText(filteredData.get(position));
     
            return convertView;
        }
        
        static class ViewHolder {
            TextView text;
        }
     
        public Filter getFilter() {
            return mFilter;
        }
     
        private class ItemFilter extends Filter {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                
                String filterString = constraint.toString().toLowerCase();
                
                FilterResults results = new FilterResults();
                
                final List<String> list = originalData;
     
                int count = list.size();
                final ArrayList<String> nlist = new ArrayList<String>(count);
     
                String filterableString ;
                
                for (int i = 0; i < count; i++) {
                    filterableString = list.get(i);
                    if (filterableString.toLowerCase().contains(filterString)) {
                        nlist.add(filterableString);
                    }
                }
                
                results.values = nlist;
                results.count = nlist.size();
     
                return results;
            }
     
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                filteredData = (ArrayList<String>) results.values;
                notifyDataSetChanged();
            }
     
        }
    }
    

    In your Activity or Fragment where of Adapter is instantiated :

    editTxt.addTextChangedListener(new TextWatcher() {
      
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            System.out.println("Text ["+s+"]");
            
            mSearchableAdapter.getFilter().filter(s.toString());                           
        }
         
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
             
        }
         
        @Override
        public void afterTextChanged(Editable s) {
        }
    });
    

    Here are the links for the original source and another example

    0 讨论(0)
  • 2020-11-22 07:01

    you can find custom list adapter class with filterable using text change in edit text...

    create custom list adapter class with implementation of Filterable:

    private class CustomListAdapter extends BaseAdapter implements Filterable{
    
        private LayoutInflater inflater;
        private ViewHolder holder;
        private ItemFilter mFilter = new ItemFilter();
    
        public CustomListAdapter(List<YourCustomData> newlist) {
            filteredData = newlist;
        }
    
        @Override
        public int getCount() {
            return filteredData.size();
        }
    
        @Override
        public Object getItem(int position) {
            return null;
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
    
            holder = new ViewHolder();
    
            if(inflater==null)
                inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
            if(convertView == null){
                convertView = inflater.inflate(R.layout.row_listview_item, null);
    
                holder.mTextView = (TextView)convertView.findViewById(R.id.row_listview_member_tv);
    
                convertView.setTag(holder);
            }else{
                holder = (ViewHolder)convertView.getTag();
            }
    
            holder.mTextView.setText(""+filteredData.get(position).getYourdata());
    
            return convertView;
        }
    
        @Override
        public Filter getFilter() {
            return mFilter;
        }
    
    
    }
    
    class ViewHolder{
        TextView mTextView;
    }
    
    private class ItemFilter extends Filter {
        @SuppressLint("DefaultLocale")
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
    
            String filterString = constraint.toString().toLowerCase();
    
            FilterResults results = new FilterResults();
    
            final List<YourCustomData> list = YourObject.getYourDataList();
    
            int count = list.size();
            final ArrayList<YourCustomData> nlist = new ArrayList<YourCustomData>(count);
    
            String filterableString ;
    
            for (int i = 0; i < count; i++) {
                filterableString = ""+list.get(i).getYourText();
                if (filterableString.toLowerCase().contains(filterString)) {
                    YourCustomData mYourCustomData = list.get(i);
                    nlist.add(mYourCustomData);
                }
            }
    
            results.values = nlist;
            results.count = nlist.size();
    
            return results;
        }
    
        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            filteredData = (ArrayList<YourCustomData>) results.values;
            mCustomListAdapter.notifyDataSetChanged();
        }
    
    }
    
    mEditTextSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if(mCustomListAdapter!=null)
                    mCustomListAdapter.getFilter().filter(s.toString());
    
            }
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    
    0 讨论(0)
  • 2020-11-22 07:04

    I hope it will be helpful for others.

    // put below code (method) in Adapter class
    public void filter(String charText) {
        charText = charText.toLowerCase(Locale.getDefault());
        myList.clear();
        if (charText.length() == 0) {
            myList.addAll(arraylist);
        }
        else
        {
            for (MyBean wp : arraylist) {
                if (wp.getName().toLowerCase(Locale.getDefault()).contains(charText)) {
                    myList.add(wp);
                }
            }
        }
        notifyDataSetChanged();
    }
    

    declare below code in adapter class

    private ArrayList<MyBean> myList;  // for loading main list
    private ArrayList<MyBean> arraylist=null;  // for loading  filter data
    

    below code in adapter Constructor

    this.arraylist = new ArrayList<MyBean>();
        this.arraylist.addAll(myList);
    

    and below code in your activity class

    final EditText searchET = (EditText)findViewById(R.id.search_et);
        // Capture Text in EditText
        searchET.addTextChangedListener(new TextWatcher() {
    
            @Override
            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub
                String text = searchET.getText().toString().toLowerCase(Locale.getDefault());
                adapter.filter(text);
            }
    
            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1,
                                          int arg2, int arg3) {
                // TODO Auto-generated method stub
            }
    
            @Override
            public void onTextChanged(CharSequence arg0, int arg1, int arg2,
                                      int arg3) {
                // TODO Auto-generated method stub
            }
        });
    
    0 讨论(0)
  • 2020-11-22 07:05

    One thing I've noticed is that whenever you are editing the list (adding items for example) as well as filtering for it, then inside the @Override getView method, you shouldn't use filteredData.get(position), as it throws an IndexOutOfBounds exception.

    Instead, what worked for me, was using the getItem(position) method, which belongs to the ArrayAdapter class.

    0 讨论(0)
提交回复
热议问题