How to use search functionality in custom list view in Android
You have to use model, listview, and customadapter with filtering for this.I have created a demo for this.
Suppose you have a model named Product, and you are displaying its content in a custom listview where name and price are displayed in a textview. I mean in a custom row having two textviews, and you want to filter the list by one of the field of custom row. Here I have filtered with "name"
Screenshots:
Initial
Filtered
Source code
Model
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(Integer price) { this.price = price; }}
Activity with custom adapter and listview
public class MainActivity extends Activity { private LinearLayout llContainer; private EditText etSearch; private ListView lvProducts; private ArrayList<Product> mProductArrayList = new ArrayList<Product>(); private MyAdapter adapter1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initialize(); // Add Text Change Listener to EditText etSearch.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Call back the Adapter with current character to Filter adapter1.getFilter().filter(s.toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count,int after) { } @Override public void afterTextChanged(Editable s) { } }); } private void initialize() { etSearch = (EditText) findViewById(R.id.etSearch); lvProducts = (ListView)findViewById(R.id.lvOS); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); mProductArrayList.add(new Product("a", 100)); mProductArrayList.add(new Product("b", 200)); mProductArrayList.add(new Product("c", 300)); mProductArrayList.add(new Product("d", 400)); mProductArrayList.add(new Product("e", 500)); mProductArrayList.add(new Product("f", 600)); mProductArrayList.add(new Product("g", 700)); mProductArrayList.add(new Product("h", 800)); mProductArrayList.add(new Product("i", 900)); mProductArrayList.add(new Product("j", 1000)); mProductArrayList.add(new Product("k", 1100)); mProductArrayList.add(new Product("l", 1200)); mProductArrayList.add(new Product("m", 1000)); mProductArrayList.add(new Product("n", 1300)); mProductArrayList.add(new Product("o", 1400)); mProductArrayList.add(new Product("p", 1500)); adapter1 = new MyAdapter(MainActivity.this, mProductArrayList); lvProducts.setAdapter(adapter1); } // Adapter Class public class MyAdapter extends BaseAdapter implements Filterable { private ArrayList<Product> mOriginalValues; // Original Values private ArrayList<Product> mDisplayedValues; // Values to be displayed LayoutInflater inflater; public MyAdapter(Context context, ArrayList<Product> mProductArrayList) { this.mOriginalValues = mProductArrayList; this.mDisplayedValues = mProductArrayList; inflater = LayoutInflater.from(context); } @Override public int getCount() { return mDisplayedValues.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } private class ViewHolder { LinearLayout llContainer; TextView tvName,tvPrice; } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.row, null); holder.llContainer = (LinearLayout)convertView.findViewById(R.id.llContainer); holder.tvName = (TextView) convertView.findViewById(R.id.tvName); holder.tvPrice = (TextView) convertView.findViewById(R.id.tvPrice); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.tvName.setText(mDisplayedValues.get(position).name); holder.tvPrice.setText(mDisplayedValues.get(position).price+""); holder.llContainer.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(MainActivity.this, mDisplayedValues.get(position).name, Toast.LENGTH_SHORT).show(); } }); return convertView; } @Override public Filter getFilter() { Filter filter = new Filter() { @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint,FilterResults results) { mDisplayedValues = (ArrayList<Product>) results.values; // has the filtered values notifyDataSetChanged(); // notifies the data with new filtered values } @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); // Holds the results of a filtering operation in values ArrayList<Product> FilteredArrList = new ArrayList<Product>(); if (mOriginalValues == null) { mOriginalValues = new ArrayList<Product>(mDisplayedValues); // saves the original data in mOriginalValues } /******** * * If constraint(CharSequence that is received) is null returns the mOriginalValues(Original) values * else does the Filtering and returns FilteredArrList(Filtered) * ********/ if (constraint == null || constraint.length() == 0) { // set the Original result to return results.count = mOriginalValues.size(); results.values = mOriginalValues; } else { constraint = constraint.toString().toLowerCase(); for (int i = 0; i < mOriginalValues.size(); i++) { String data = mOriginalValues.get(i).name; if (data.toLowerCase().startsWith(constraint.toString())) { FilteredArrList.add(new Product(mOriginalValues.get(i).name,mOriginalValues.get(i).price)); } } // set the Filtered result to return results.count = FilteredArrList.size(); results.values = FilteredArrList; } return results; } }; return filter; } }}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <EditText android:id="@+id/etSearch" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <ListView android:id="@+id/lvProducts" android:layout_width="fill_parent" android:layout_height="wrap_content" ></ListView> </LinearLayout>
row.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/llContainer" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/tvName" android:layout_width="0dp" android:layout_height="wrap_content" android:singleLine="true" android:layout_weight="1" /> <TextView android:id="@+id/tvPrice" android:layout_width="0dp" android:layout_height="wrap_content" android:singleLine="true" android:layout_weight="1" /></LinearLayout>
Implement filterable in your customadapter class.
public class MainActivity extends AppCompatActivity {String names[] = {"Apple","Banana","Kiwi","Oranges","Watermelon"};String emails[] = {"This is apple","This is banana","This is kiwi","This is oranges","This is watermelon"};int images[] = {R.drawable.apple,R.drawable.banana,R.drawable.kiwi,R.drawable.oranges,R.drawable.watermelon};List<ItemsModel> itemsModelList = new ArrayList<>();ListView listView;CustomAdapter customAdapter;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = findViewById(R.id.listview); for(int i = 0;i < names.length;i++){ ItemsModel itemsModel = new ItemsModel(names[i],emails[i],images[i]); itemsModelList.add(itemsModel); } customAdapter = new CustomAdapter(itemsModelList,this); listView.setAdapter(customAdapter);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.search_menu,menu); MenuItem menuItem = menu.findItem(R.id.searchView); SearchView searchView = (SearchView) menuItem.getActionView(); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { Log.e("Main"," data search"+newText); customAdapter.getFilter().filter(newText); return true; } }); return true;}@Overridepublic boolean onOptionsItemSelected(@NonNull MenuItem item) { int id = item.getItemId(); if(id == R.id.searchView){ return true; } return super.onOptionsItemSelected(item);}public class CustomAdapter extends BaseAdapter implements Filterable { private List<ItemsModel> itemsModelsl; private List<ItemsModel> itemsModelListFiltered; private Context context; public CustomAdapter(List<ItemsModel> itemsModelsl, Context context) { this.itemsModelsl = itemsModelsl; this.itemsModelListFiltered = itemsModelsl; this.context = context; } @Override public int getCount() { return itemsModelListFiltered.size(); } @Override public Object getItem(int position) { return itemsModelListFiltered.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { View view = getLayoutInflater().inflate(R.layout.row_items,null); TextView names = view.findViewById(R.id.name); TextView emails = view.findViewById(R.id.email); ImageView imageView = view.findViewById(R.id.images); names.setText(itemsModelListFiltered.get(position).getName()); emails.setText(itemsModelListFiltered.get(position).getEmail()); imageView.setImageResource(itemsModelListFiltered.get(position).getImages()); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("main activity","item clicked"); startActivity(new Intent(MainActivity.this,ItemsPreviewActivity.class).putExtra("items",itemsModelListFiltered.get(position))); } }); return view; } @Override public Filter getFilter() { Filter filter = new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults filterResults = new FilterResults(); if(constraint == null || constraint.length() == 0){ filterResults.count = itemsModelsl.size(); filterResults.values = itemsModelsl; }else{ List<ItemsModel> resultsModel = new ArrayList<>(); String searchStr = constraint.toString().toLowerCase(); for(ItemsModel itemsModel:itemsModelsl){ if(itemsModel.getName().contains(searchStr) || itemsModel.getEmail().contains(searchStr)){ resultsModel.add(itemsModel); } filterResults.count = resultsModel.size(); filterResults.values = resultsModel; } } return filterResults; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { itemsModelListFiltered = (List<ItemsModel>) results.values; notifyDataSetChanged(); } }; return filter; }}
}
full tutorial can be found here:listview with search and onItemClickListner
for this, you first need to add an edittext, where you will type to filter data from the list,
then enable filteration in the list,
editText = (EditText) findViewById(R.id.searchList); adapter = new CustomListViewAdapter(this, R.layout.list_row, rowItems); listView.setAdapter(adapter); listView.setTextFilterEnabled(true);
Then you need to add TextChangeListener()
for the edittext,
editText.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } public void afterTextChanged(Editable arg0) { MyActivityName.this.adapter.getFilter().filter(arg0); } });