javaandroidlistviewandroid-arrayadapterandroid-filterable

How to apply search filter using startsWith on a simple listview in android


I have a ListView that gets data from a database. I applied the search filter on it, but it doesn't filter as I want. what I want is to filter with the first letter not middle or contains.

Here is the code:

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

    ListView dicList; 
    EditText editSearch;
    ArrayAdapter<String> adapterListOfWord;
    ArrayList<String> mSource = new ArrayList<String>();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editSearch = findViewById(R.id.edit_search);
        dicList = findViewById(R.id.dic_list);

        adapterListOfWord = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mSource);
        dicList.setAdapter(adapterListOfWord);

        editSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                // the problem is here, i want to search with the first letter not middle or contains.
                adapterListOfWord.getFilter().filter(charSequence);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }
}

I don't know how to implement and apply filterable to my project according to my codes and change the contains() to startsWith() to reach my goal.
I really appreciate your help.
Thanks in advance.


Solution

  • You need to use a customized adapter instead of the default one, and override the getFilter() to filter the list with the String's startsWith() method:

    Adapter:

    public class StartsWithArrayAdapter extends ArrayAdapter<String> implements Filterable {
    
        private final List<String> mList = new ArrayList<>();
        private List<String> mFilteredList = new ArrayList<>();
    
        public StartsWithArrayAdapter(Context context, int textViewResourceId, ArrayList<String> list) {
            super(context, textViewResourceId, list);
            this.mList.addAll(list);
            this.mFilteredList.addAll(list);
        }
    
        @Override
        public int getCount() {
            return mFilteredList.size();
        }
    
        @NonNull
        @Override
        public Filter getFilter() {
            return new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence charSequence) {
                    String charString = charSequence.toString();
                    if (charString.isEmpty()) {
                        mFilteredList = mList;
                    } else {
                        List<String> filteredList = new ArrayList<>();
                        for (String listItem : mList) {
                            if (listItem.toLowerCase().startsWith(charString.toLowerCase())) {
                                filteredList.add(listItem);
                            }
                        }
                        mFilteredList = filteredList;
                    }
    
                    FilterResults filterResults = new FilterResults();
                    filterResults.values = mFilteredList;
                    return filterResults;
                }
    
                @Override
                @SuppressWarnings("unchecked")
                protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                    mFilteredList = (ArrayList<String>) filterResults.values;
                    clear();
                    addAll(mFilteredList);
                    notifyDataSetChanged();
                }
            };
    
        }
        
    }
    

    Usage in your code:

    public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    
    
        StartsWithArrayAdapter adapterListOfWord;
        
        // rest of code
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            // omitted code
            
            adapterListOfWord = new StartsWithArrayAdapter(this, android.R.layout.simple_list_item_1, mSource);
            
            // rest of code
    
        }
    }