Implement "Search" functionality on RecyclerView - android

I am trying to search on the recyclerview items. For this I've implemented Filterable. Problem is - instaed of matched items, I am getting the whole list of items. Here is the constructor of the Adapter class :
public RecyclerAdapter (ArrayList<List<ResponseModel>> items) {
this.items = items; // original items
this.tempItems = items; // for searching purpose
}
Here is the overrided method :
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
if (charString.isEmpty()) {
items = tempItems;
} else {
ArrayList<List<ResponseModel>> filteredList = new ArrayList<>();
for (List<ResponseModel> responseModel : tempItems) {
for (int i =0; i < tempItems.size() ; i++) {
if (responseModel.get(i).getName().toLowerCase().contains(charString)){
filteredList.add(responseModel);
}
}
}
items = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = items;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
items = (ArrayList<List<ResponseModel>>) results.values;
notifyDataSetChanged();
}
};
}
Here is onCreate optionsMenu inside a Fragment class :
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.options_menu, menu);
MenuItem item = menu.findItem(R.id.action_search);
SearchView sv = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItemCompat.setActionView(item, sv);
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return true;
}
});
}

Try below in you publishResultsMethod
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
items.clear();
items.addAll((ArrayList<List<ResponseModel>>) results.values);
notifyDataSetChanged();
}

Related

How to display “no results found” using Searchview

Here is my code in "if (query == null)." As you can see, I don't put any code there because I don't know how to display "no result(s) found" in the RecyclerView if the user doesn't match his input to the searchview. I'm using RecyclerView to display the search results of the user.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_main, menu);
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_filter_search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getActivity().getComponentName()));
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setQueryHint(getResources().getString(R.string.search_hint));
// listening to search query text change
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// filter recycler view when query submitted
mAdapter.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String query) {
// filter recycler view when text is changed
mAdapter.getFilter().filter(query);
return false;
}
});
super.onCreateOptionsMenu(menu, inflater);
}
in the adapter
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
categoriesFiltered = categorieslist;
} else {
List<CategoriesP> filteredList = new ArrayList<>();
for (CategoriesP row : categorieslist) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
//|| row.getPhone().contains(charSequence)
if (row.getName().toLowerCase().contains(charString.toLowerCase()) ) {
filteredList.add(row);
}
}
categoriesFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = categoriesFiltered;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults filterResults) {
categoriesFiltered = (ArrayList<CategoriesP>) filterResults.values;
notifyDataSetChanged();
}
};
}
Set TextView in your XML and set this line android:visibility="gone" for it.
in your Activity put this code...
if (listMesage.isEmpty()) {
mRecyclerMessage.setVisibility(View.GONE);
mTxtEmpty.setVisibility(View.VISIBLE);
}
else {
mRecyclerMessage.setVisibility(View.VISIBLE);
mTxtEmpty.setVisibility(View.GONE);
}

How to make search view with modal in Android

I want to make a searchView like this image below. The searchView is received data from local database then it filters data like AutoCompleteTextView.
How can i make it?
Here is image:
enter image description here
I use RecyclerView for list display item, and in Adapter I implements a Filterable:
private List<Bank> banksList;
private List<Bank> bankListFiltered;
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
if (charString.isEmpty()) {
bankListFiltered = banksList;
} else {
List<Bank> filteredList = new ArrayList<>();
for (Bank row : banksList) {
String shortName = row.getShortName().toLowerCase();
if (shortName.contains(charString)) {
filteredList.add(row);
}
}
bankListFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = bankListFiltered;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
bankListFiltered = (ArrayList<Bank>) results.values;
notifyDataSetChanged();
}
};
}
#Override
public int getItemCount() {
return bankListFiltered.size();
}
public BanksAdapter(List<Bank> banksList) {
this.banksList = banksList;
this.bankListFiltered = banksList;
}
And in my activity, add event for SearchView:
new SearchView(this).setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
banksAdapter.getFilter().filter(newText);
return true;
}
});

Setting previous results back in recycler view when a text is delected from Search view's Filter

I am having trouble with Setting previous results back in recyclerView when a text is deleted from searchView's Filter box. I use the following code in the adapter which filters the data finely. But the thing is it does not set the previous values in the recyclerView when the search text is deleted from the search view.
recyclerView adapter's get filter method
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
results = names;
} else {
ArrayList<tab> filteredList = new ArrayList<>();
for (tab row : names) {
// name match condition. this might differ depending on your requirement
// here we are looking for name or phone number match
if (row.getName().toLowerCase().contains(charString.toLowerCase()) || row.getmsg().contains(charSequence)) {
filteredList.add(row);
}
}
results = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = results;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
names = (ArrayList<tab>) filterResults.values;
// refresh the list with filtered data
notifyDataSetChanged();
}
};
}
Main activity code
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
searchView.setMaxWidth(Integer.MAX_VALUE);
// listening to search query text change
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// filter recycler view when query submitted
gtxx.getFilter().filter(query);
// gtxx.notifyDataSetChanged();
return false;
}
#Override
public boolean onQueryTextChange(String query) {
// filter recycler view when text is changed
gtxx.getFilter().filter(query);
//gtxx.notifyDataSetChanged();
return false;
}
});
return true;
}
Setting value in the adapter
gtxx = new listadapttor(con_list);
recyclerView.setAdapter(gtxx);
In your adapter create two list, with the same data. Let say second list is temporary list. Set adapter using that list and do filtering on the second list from first list. Refer the code below:
private List<YourObject> tempList;
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//this is the main list, which contains filtered items
//and tempList always contains original data.
//so when empty text is passed to filterable it will reset
//the list using original data from tempList
mainList = (List<YourObject>) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.toString().length() > 0) {
List<YourObject> filteredItems = new ArrayList<YourObject>();
for (int i = 0; i < tempList.size(); i++) {
YourObject data = tempList.get(i);
if ((data.getName() != null && data.getName().toLowerCase().contains(constraint.toString().toLowerCase()))) { //Your filtering code here
filteredItems.add(data);
}
}
results.count = filteredItems.size();
results.values = filteredItems;
}
else
{
synchronized (this) {
results.values = tempList;
results.count = tempList.size();
}
}
return results;
}
};
return filter;
}

Recyclerview item long press not working using search view?

I have an app which contains recyclerview with searchview on long press item is working fine in case of a normal list, But when I type anything using searchview it comes on the top but when I click on that item I am always getting an item from the normal list at position 0.How do I resolve this issue.
code:-
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
if (charString.isEmpty()) {
mFilterList = models;
} else {
ArrayList<UserListingModel> filteredList = new ArrayList<>();
for (UserListingModel userListingModel : models) {
if (userListingModel.getUseName().toLowerCase().contains(charString.toLowerCase()) || userListingModel.getUseName().toUpperCase().contains(charString.toUpperCase())) {
filteredList.add(userListingModel);
}
}
mFilterList = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mFilterList;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mFilterList = (ArrayList<UserListingModel>) results.values;
notifyDataSetChanged();
}
};
}
searchview code:-
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
Log.e(TAG, "Position");
Users.mAdapter.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
Users.mAdapter.getFilter().filter(newText);
return false;
}
});

how to check if list is filtered or not with boolean

I've implemented searchView filter on my recycler view. Now I need to find when my list is filtered and when it is not.
This is my Filterable implementation in my custom adapter:
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
dataList = (List<ProductLight>) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
List<ProductLight> FilteredArrayNames = new ArrayList<ProductLight>();
constraint = constraint.toString().toLowerCase();
for (int i = 0; i < dataListFilter.size(); i++) {
ProductLight dataNames = dataListFilter.get(i);
if (dataNames.getTitle().toLowerCase().startsWith(constraint.toString())){
FilteredArrayNames.add(dataNames);
}
}
results.count = FilteredArrayNames.size();
results.values = FilteredArrayNames;
return results;
}
};
return filter;
}
And in my Fragment(wich has searchview in optionMenu) I'm filtering my list like this:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu, menu);
MenuItem item = menu.findItem(R.id.search_menu);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
isListFiltered = true ;
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
});
Now I don't know where should I switch isListFiltered to false.

Categories

Resources