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;
}
});
Related
I have a RecyclerView. I want to make it filterable with SearchView. My application is based on Android Architecture Components.
I created a filter method for searchView .When i search something it's work but when i clear text from searchView ,list do not change and still shows search data.
Activity:
private StudentAdapter mAdapter;
mAdapter = new StudentAdapter(this);
recyclerView.setAdapter(mAdapter);
//ViewModel
StudentViewModelFactory factory = new StudentViewModelFactory(mDb, mClassId);
StudentViewModel viewModel = ViewModelProviders.of(this, factory).get(StudentViewModel.class);
viewModel.getStudentEntries().observe(this, studentEntries -> mAdapter.setStudents(studentEntries));
//SearchView
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
#Override
public boolean onQueryTextSubmit(String query){
return false;
}
#Override
public boolean onQueryTextChange(String newText){
mAdapter.getFilter().filter(newText);
return false;
}
});
Adapter:
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.itemHolder> {
private List<StudentEntry> mStudentEntries;
private List<StudentEntry> filteredStudentEntries;
public StudentAdapter(Context context) {
this.context = context;
}
public void setStudents(List<StudentEntry> studentEntries) {
this.mStudentEntries = studentEntries;
notifyDataSetChanged();
}
public void setPerformances(List<PerformanceEntry> performanceEntries) {
this.mPerformanceEntries = performanceEntries;
notifyDataSetChanged();
}
.
.
.
public Filter getFilter() {
return new Filter() {
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mStudentEntries = (List<StudentEntry>) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
filteredStudentEntries = null;//avaz shod vali test nashod
if (constraint.length() == 0) {
filteredStudentEntries = mStudentEntries;
} else {
filteredStudentEntries = getFilteredResults(constraint.toString().toLowerCase());
}
FilterResults results = new FilterResults();
results.values = filteredStudentEntries;
return results;
}
};
}
protected List<StudentEntry> getFilteredResults(String constraint) {
List<StudentEntry> results = new ArrayList<>();
for (StudentEntry item : mStudentEntries) {
if (item.getStudentName().toLowerCase().contains(constraint)
|| item.getStudentId().toLowerCase().contains(constraint)) {
results.add(item);
}
}
return results;
}
}
Change :
private List<StudentEntry> filteredStudentEntries;
To :
private ArrayList<StudentEntry> arrayList = new ArrayList<>();
And Change :
public void setStudents(List<StudentEntry> studentEntries) {
this.mStudentEntries = studentEntries;
notifyDataSetChanged();
}
to :
public void setStudents(List<StudentEntry> studentEntries) {
this.mStudentEntries = studentEntries;
arrayList.addAll(mStudentEntries);
notifyDataSetChanged();
}
And change filter method :
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString().toLowerCase().trim();
mStudentEntries.clear();
if (constraint.length() == 0) {
mStudentEntries.addAll(arrayList);
} else {
for (StudentEntry item : arrayList) {
if (item.getStudentName().toLowerCase(Locale.getDefault()).contains(constraint)
|| item.getStudentId().toLowerCase(Locale.getDefault()).contains(constraint)) {
mStudentEntries.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = mStudentEntries;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
notifyDataSetChanged();
}
};
}
And don't forget to implements Filterable in adapter class.
Refer the below answer it will help,
Search text will pass to recyclerView by below code.
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return true;
}
Then RecyclerViewAdapter class should implements Filterable
public class DashboardRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {
//constructor loads data to dataList
DashboardRecyclerViewAdapter(ArrayList<Object> data,Context context)
{
this.context = context;
this.dataList = data;
this.filteredDataList = new ArrayList<>(data.size());
this.filteredDataList.addAll(dataList);
}
//override this method, it gets the SerchText and then compares with dataList
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
ArrayList<Object> filteredDataList_temp = new ArrayList<>();
String charString = charSequence.toString().toLowerCase();
if (charString.isEmpty() || charString.trim().length() == 0 ) {
filteredDataList_temp = dataList;
} else {
for (Object row : dataList) {
FoodDetail r = (FoodDetail) row;
if (foodName.contains(charString)) {
filteredDataList_temp.add(row);
}
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = filteredDataList_temp;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (filteredDataList != null) {
filteredDataList.clear();
filteredDataList.addAll((ArrayList<Object>) results.values);
notifyDataSetChanged(); //once completed Then RecyclerView updated with only searched List
}
}
};
}
I am trying to search a RecylerView with EditText, i follow some tutorial and i get Error NullPointerException. my RecyclerView is working good , but my search program is not working.
this is my Adapter Code
public class ListDefoodAdapter extends RecyclerView.Adapter<ListDefoodAdapter.CategoryViewHolder> implements Filterable {
private Context context;
private ArrayList<DefoodListData> listDefood;
private ArrayList<DefoodListData> listFilter;
public ListDefoodAdapter(Context context) {
this.context = context;
}
public ArrayList<DefoodListData> getListDefood() {
return listDefood;
}
public void setListDefood(ArrayList<DefoodListData> listDefood) {
this.listDefood = listDefood;
}
#NonNull
#Override
public CategoryViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemRow = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_transaksidefood, viewGroup, false);
return new CategoryViewHolder(itemRow);
}
public Filter getFilter(){
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
if (charString.isEmpty()){
listDefood = listFilter;
} else {
ArrayList<DefoodListData> filteredList = new ArrayList<>();
for (DefoodListData row : listFilter){
String id = String.valueOf(row.getId());
if (id.toLowerCase().contains(charString.toLowerCase()) ||
row.getNamaUser().toLowerCase().contains(charString.toLowerCase()) ||
row.getNamaDriver().toLowerCase().contains(charString.toLowerCase())){
filteredList.add(row);
}
}
listDefood = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = listDefood;
return filterResults;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
listDefood = (ArrayList<DefoodListData>) results.values;
notifyDataSetChanged();
}
};
}
#Override
public int getItemCount() {
return getListDefood().size();
}
}
and this is my code in fragment
private void searchData(){
btn_search.setOnClickListener(v -> {
String keySearch = edt_cari.getText().toString();
listDefoodAdapter.getFilter().filter(keySearch);
});
}
but i get error null on method getItemCount(). Please help me to solve this problem
there is an issue in your data assign in listFilter.
you are adding data in listDefood in below method
public void setListDefood(ArrayList<DefoodListData> listDefood) {
this.listDefood = listDefood;
}
but you are not adding a list in listFilter.
You need to add list in Both array.
public void setListDefood(ArrayList<DefoodListData> listDefood) {
this.listDefood = listDefood;
this.listFilter = listDefood;
}
Assign filtered list size to filter result.
try with this
public void setListDefood(ArrayList<DefoodListData> listDefood) {
this.listDefood = listDefood;
this.listFilter = listDefood;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
listDefood = (List<DefoodListData >) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
ArrayList<DefoodListData> filteredList = new ArrayList<>();
for (DefoodListData row : listFilter) {
if (String.valueOf(row.getId().toLowerCase().trim().contains(charString)) ||
row.getNamaUser().toLowerCase().trim().contains(charString) ||
row.getNamaDriver().toLowerCase().trim().contains(charString)) {
filteredList.add(row);
}
}
results.count = filteredList.size();
results.values = filteredList;
return results;
}
};
}
hi all I have implemented SearchView inside RecyclerView but when I search character name it is not searching any name and I have followed this tutorial
below my adapter class where I have implemented recyclerview with
Filtarable
public class LeovegasAdapter extends RecyclerView.Adapter implements Filterable {
private List<Hero> heros;
private List<Hero> filtarableList;
public LeovegasAdapter(List<Hero> heros) {
this.heros = heros;
filtarableList = filtarableList;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.hero_list, parent, false);
return new CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
Hero hero = heros.get(position);
holder.heroId.setText(hero.getId());
holder.heroName.setText(hero.getName());
}
#Override
public int getItemCount() {
return heros.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
filtarableList = heros;
} else {
ArrayList<Hero> filteredList = new ArrayList<>();
for (Hero hero : heros) {
if (hero.getId().toLowerCase().contains(charString) || hero.getName().toLowerCase().contains(charString)) {
filteredList.add(hero);
}
}
filtarableList = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = filtarableList;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filtarableList = (List<Hero>) results.values;
notifyDataSetChanged();
}
};
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView heroId, heroName;
public CustomViewHolder(View view) {
super(view);
heroId = (TextView) view.findViewById(R.id.heroId);
heroName = (TextView) view.findViewById(R.id.heroName);
}
}
}
below my MainActivity.java
public class MainActivity extends AppCompatActivity {
public LeovegasAdapter leovegasAdapter;
public static final String publicKey = "4089ee37331d8211b080b047c58f6970";
public static final String privateKey = "18ccbcb58fdd12c22821f8b633a06f2b433d16c3";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LeoVegasInterface leoVegasInterface = LeoVegasClient.getApiService();
String ts = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
String hash = Hasher.md5(ts + privateKey + publicKey);
Call<LeoVegas> callHeroes = leoVegasInterface.getHeroes(ts, publicKey, hash);
callHeroes.enqueue(new Callback<LeoVegas>() {
#Override
public void onResponse(Call<LeoVegas> call, Response<LeoVegas> response) {
LeoVegas leoVegas = response.body();
Data data = leoVegas.getData();
Hero[] heroes = data.getResults();
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
leovegasAdapter = new LeovegasAdapter(Arrays.asList(heroes));
RecyclerView.LayoutManager eLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(eLayoutManager);
recyclerView.setAdapter(leovegasAdapter);
}
#Override
public void onFailure(Call<LeoVegas> call, Throwable t) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem search = menu.findItem(R.id.search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(search);
search(searchView);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
private void search(SearchView searchView) {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
leovegasAdapter.getFilter().filter(newText);
return true;
}
});
}
}
Change your below code
Few changes
Clear the list
Use addAll to fill with the result
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
//Updated code
String charString = charSequence.toString();
ArrayList<Hero> filteredList = new ArrayList<>();
if (charString.isEmpty()) {
filteredList.addAll(filtarableList);
} else {
ArrayList<Hero> filteredList = new ArrayList<>();
for (Hero hero : heros) {
if (hero.getId().toLowerCase().contains(charString) || hero.getName().toLowerCase().contains(charString)) {
filteredList.add(hero);
}
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = filteredList;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//Update code
heros.clear();
if (results == null)
heros.addAll(mFilterConversations);
else {
heros.addAll((List<Hero>) results.values);
}
notifyDataSetChanged();
}
};
}
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;
}
});
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();
}