Problem: Adding a list item prevents filter method from working. Otherwise the filter works correctly.
Expected: That the items and database are correctly updated from the both add item and filter methods.
Tested:
Filter on current list works and applies the layout.
Filter on filtered list works and applies the layout.
Filter with no constraint loads the full list and applies the layout.
Adding item before filter works and applies the layout.
Adding item after filter works and applies the layout.
Filter after adding item fails to filter results and applies no changes to the layout. No run time errors are provided.
Probable Solution: I thought I was missing an assignment to the items list to grab the updated version of the list. After checking it seems that both add item and filter methods are grabbing the updated list. I am starting to think I don't understand how the filter method works and that I am missing a method or line that the filter needs to refresh. Would appreciate suggestions on how to find what I am missing.
private void addProjectItem() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = getLayoutInflater().inflate(R.layout.project_add_layout, null);
final EditText title = view.findViewById(R.id.addProjectTitle);
final EditText description = view.findViewById(R.id.addProjectDescription);
builder.setNegativeButton(
android.R.string.cancel,
(dialog, which) -> dialog.cancel()
);
builder.setPositiveButton(
android.R.string.ok,
(dialog, which) -> {
if (!title.getText().toString().isEmpty() && !description.getText().toString().isEmpty()) {
ProjectItem item = new ProjectItem(
title.getText().toString(),
description.getText().toString(),
appDataManager.getUid(),
false
);
projectListManager.addItem(item);
adapter.updateItems(projectListManager.getList());
} else {
Toast.makeText(SecondActivity.this, projectAddError, Toast.LENGTH_SHORT).show();
}
}
);
builder.setView(view);
builder.show();
}
private class ProjectItemAdapter extends ArrayAdapter<ProjectItem> implements Filterable {
private Context context;
private List<ProjectItem> items;
private ImageButton projectCompleteButton;
private ImageButton projectDescriptionButton;
private TextView itemTitle;
private ImageButton projectJoinButton;
private ProjectItemAdapter( Context context, List<ProjectItem> items) {
super(context, -1, items);
this.context = context;
this.items = items;
}
#NonNull
#Override
public Filter getFilter() {
return projectFilter;
}
private final Filter projectFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
List<ProjectItem> found = new ArrayList<>();
if(constraint == null || constraint.length() == 0) {
found.addAll(projectListManager.getList());
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for(ProjectItem item : items){
if(item.getTitle().toLowerCase().contains(filterPattern)) {
found.add(item);
}
}
}
results.values = found;
results.count = found.size();
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
clear();
addAll((List)results.values);
notifyDataSetChanged();
}
};
public void updateItems(List<ProjectItem> items) {
this.items = items;
notifyDataSetChanged();
}
#Override
public int getCount() {
return items.size();
}
#NonNull
#Override
public View getView(int position, View convertView, #NonNull ViewGroup parent) {
// Removed as there is nothing that manipulates the list item.
return convertView;
}
}
}
Problem was with the publish results not referencing the items list and properly casting results as a collections.
Solution:
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
items.clear();
items.addAll((Collection<? extends ProjectItem>) results.values);
notifyDataSetChanged();
}
Related
I get correct objects in filtered list in publishResults() function but the filtered list is not displayed on the screen after filtering.
Following is the code for CityAdapter class inhereted from ArrayAdapter class.
IT seems like notifyDataSetChanged() isn't working?
Please inform why list is not displaying.What's wrong in the code.
import...
public class CityListAdapter extends ArrayAdapter<City> implements Filterable {
private ArrayList<City> cities;
private ArrayList<City> filtered_list;
public CityListAdapter(Context context, int resource, ArrayList<City>cities) {
super(context, resource, cities);
this.cities = cities;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, ViewGroup parent) {
Holder holder = new Holder();
if(convertView == null) {
LayoutInflater inflator = LayoutInflater.from(getContext());
convertView = inflator.inflate(R.layout.adapter_view,parent,false);
holder.box = (CheckBox) convertView.findViewById(R.id.checkBox);
holder.name = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(holder);
}
else {
holder = (Holder) convertView.getTag();
}
City city = getItem(position) ;
holder.name.setText(city.getName());
return convertView;
}
private class Holder {
CheckBox box;
TextView name;
}
#NonNull
#Override
public Filter getFilter() {
return new CityFilter();
}
private class CityFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
filtered_list = new ArrayList<>();
if (constraint != null && constraint.length()!= 0) {
for (int i = 0; i < cities.size(); i++) {
if (cities.get(i).getName().contains(constraint)) {
filtered_list.add(cities.get(i));
showMessage(cities.get(i).getName() + "added");
}
}
}
results.values = filtered_list;
results.count = filtered_list.size();
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filtered_list = (ArrayList<City>) results.values;
int size =filtered_list.size();
showMessage("Data set changed"+String.format("%d", size));
notifyDataSetChanged();
}
}
public void showMessage(String message) {
Toast toast = Toast.makeText(getContext(), message, Toast.LENGTH_LONG);
toast.show();
}
}
You need to have a full list of items in the very beginning (i.e. in the constructor) assigned to the filtered list; so that they can have the entire list when there is no filtering of results (empty search) and that occurs whenever you instantiate the adapter.
public CityListAdapter(Context context, int resource, ArrayList<City>cities) {
super(context, resource, cities);
this.cities = cities;
this.filtered_list = cities; // <<<<< Change here
}
Side Note
Also override getCount() to avoid IndexOutOfBoundsException when reaching the end of the list on scroll whenever the original list size not equal to the filtered list size.
As the original list is cities, when you make filtering, its size will shrink down, so you need only to get the filtered list size not the original list size to avoid IndexOutOfBoundsException.
So add this to the adapter:
#Override
public int getCount() {
return filtered_list.size();
}
A search view is implemented in action bar, the search works fine, but for example,
If user search for two characters pa, my list contains 2 data related to the related to pa i.e., pack1,pack2 then data loads in the recycler view. now if user enter another character l, to the previous characters pa, now my search view has pal , but array list doesn't match with the search, the list doesn't contain any item with pal. i.e., now the recycler view is empty. now, if I clear the character l, the list gets reloaded with data pack1, pack2, but result loads 2 times i.e., instead of showing 2 items in recyclerview, it shows 4 items in total.
It is duplicating the items, when the search is cleared.
searchview
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_order, menu);
searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
mOrderAdapter.getFilter().filter(query);
searchView.clearFocus();
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
if(newText.length()==0){
getData();
searchView.clearFocus();
}
mOrderAdapter.getFilter().filter(newText);
return true ;
}
});
return true;
}
Filter code
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
if (charString.isEmpty()||charString.length()==0) {
mListFilter = mOrderArrayList;
} else {
List<Order> filteredList = new ArrayList<>();
ArrayList<Order> templist=new ArrayList<Order>();
for (Order ord : mOrderArrayList) {
if (ord.getOs_OrderNo().toLowerCase().contains(charString.toLowerCase())
|| ord.getItemName().toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(ord);
templist.addAll(mListFilter);
}
}
mOrderArrayList.removeAll(templist);
mOrderArrayList.addAll(filteredList);
mListFilter = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mListFilter;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mListFilter = (ArrayList<Order>) results.values;
notifyDataSetChanged();
}
};
}
Any help is really appreciated.
Adapter code
public class OrderAdapter extends RecyclerView.Adapter<OrderAdapter.MyViewHolder> implements Filterable {
private Context mContext;
private List<Order> mListFilter,mOrderArrayList;
private SharedPreferences sharedPreferences;
private Resources r;
public OrderAdapter(Context context, ArrayList<Order> orderList) {
mContext = context;
mListFilter = orderList;
mOrderArrayList = orderList;
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
r = context.getResources();
}
class MyViewHolder extends RecyclerView.ViewHolder {
private TextView orderNoView, itemNameView, qtyView, statusView, companyNameView;
private Order currentItem;
MyViewHolder(View view) {
super(view);
orderNoView = view.findViewById(R.id.orderNo);
itemNameView = view.findViewById(R.id.item);
qtyView = view.findViewById(R.id.qty);
statusView = view.findViewById(R.id.status);
companyNameView = view.findViewById(R.id.company);
}
void bind (Order om) { //<--bind method allows the ViewHolder to bind to the data it is displaying
orderNoView.setText(om.getOs_OrderNo());
itemNameView.setText(String.valueOf(om.getItemName()));
qtyView.setText("Qty - " + String.valueOf(om.getOs_Qty()));
statusView.setText(om.getStatusName());
if (sharedPreferences.getString(r.getString(R.string.key_CompanyInUser), "").equals("0")){
companyNameView.setVisibility(View.GONE);
} else {
companyNameView.setText(om.getCustomerName());
}
currentItem = om; //<-- keep a reference to the current item
}
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.adapter_order, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
Order item = mListFilter.get(position);
holder.bind(item);
}
#Override
public int getItemCount() {
return mListFilter.size();
}
#Override
public int getItemViewType(int position){
return position;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
List<Order> filteredList = new ArrayList<>();
if (charString.isEmpty()||charString.length()==0) {
filteredList.addAll(mOrderArrayList);
} else {
for (Order ord : mOrderArrayList) {
if (ord.getOs_OrderNo().toLowerCase().contains(charString.toLowerCase())
|| ord.getItemName().toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(ord);
}
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = filteredList;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mListFilter = (ArrayList<Order>) results.values;
notifyDataSetChanged();
}
};
}
}
Clicklistener code
brandView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), brandView,
new RecyclerTouchListener.ClickListener() {
#Override
public void onClick(View view, int position) {
isRefreshData = true;
startActivity(new Intent(mContext, ViewOrderDetails.class).putExtra("Key-Intent-OrderNo",mOrderArrayList.get(position).getOs_OrderNo()).putExtra("Key-Intent-BrandName",mOrderArrayList.get(position).getos_BrandName()));
}
#Override
public void onLongClick(View view, int position) {
}
}));
Its because you are using addAll inside a loop in #performFiltering . Also why you have two local list for filtering? Check the method below it should work . i have removed the extra code and code which is causing the issue .
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
List<Order> filteredList = new ArrayList<>();
if (charString.isEmpty()||charString.length()==0) {
filteredList.addAll(mOrderArrayList);
} else {
for (Order ord : mOrderArrayList) {
if (ord.getOs_OrderNo().toLowerCase().contains(charString.toLowerCase())
|| ord.getItemName().toLowerCase().contains(charString.toLowerCase())) {
filteredList.add(ord);
}
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = filteredList;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mListFilter = (ArrayList<Order>) results.values;
notifyDataSetChanged();
}
};
}
I have a Search filter which has to filter the items based on the text input. Each list item consists of two TextViews and one ImageView. I have attached adapters and the filter is working fine with the two textviews but the corresponding ImageViews are not getting filtered (the order of images is not changing).
I tried to change the code in several ways but its not working. In here, my Adapter extends ArrayAdapter. I tried using the BaseAdapter too, but still doesn't work
My Adapter class:
import de.hdodenhof.circleimageview.CircleImageView;
public class ChefSearchResultAdapter extends ArrayAdapter<ChefSearchItem> implements Filterable {
private ArrayList<ChefSearchItem> modelValues;
private List<ChefSearchItem> mOriginalValues;
private Context context;
private static class ViewHolder {
TextView userName;
TextView userAdmirers;
CircleImageView userProfileImage;
}
public ChefSearchResultAdapter(Context context, ArrayList<ChefSearchItem> chefs) {
super(context, 0, chefs);
modelValues = chefs;
this.context=context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
ChefSearchItem chef = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
final ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
// If there's no view to re-use, inflate a brand new view for row
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.chef_search_listitem, parent, false);
viewHolder.userName = convertView.findViewById(R.id.user_name);
viewHolder.userAdmirers = convertView.findViewById(R.id.user_admirers);
viewHolder.userProfileImage = convertView.findViewById(R.id.profile_image);
// Cache the viewHolder object inside the fresh view
convertView.setTag(viewHolder);
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) convertView.getTag();
}
final StorageReference storageReference = FirebaseStorage.getInstance().getReference("Users").child(chef.userUID);
storageReference.child("Profile Pic").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
//Picasso.get().load(uri).into(viewHolder.userProfileImage);
Picasso.get()
.load(uri)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(viewHolder.userProfileImage, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
Picasso.get()
.load(uri)
.into(viewHolder.userProfileImage, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError(Exception e) {
Log.v("Picasso","Could not fetch image");
}
});
}
});
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle any errors
}
});
// Populate the data from the data object via the viewHolder object
// into the template view.
viewHolder.userName.setText(chef.userName);
viewHolder.userAdmirers.setText(chef.userAdmirers);
//Set on click to listitem
LinearLayout listItem = convertView.findViewById(R.id.chef_listitem);
listItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Navigate user to selected chef profile
Intent i=new Intent(context,ChefsViewActivity.class);
i.putExtra("UID",chef.userUID);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
});
// Return the completed view to render on screen
return convertView;
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
modelValues.clear();
modelValues.addAll((ArrayList<ChefSearchItem>) results.values);
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// Holds the results of a filtering values
List<ChefSearchItem> FilteredArrList = new ArrayList<>();
if (mOriginalValues == null) {
mOriginalValues = new ArrayList<>(modelValues); // saves
}
/********
*
* 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 {
Locale locale = Locale.getDefault();
constraint = constraint.toString().toLowerCase(locale);
for (int i = 0; i < mOriginalValues.size(); i++) {
ChefSearchItem model = mOriginalValues.get(i);
String data = model.userName;
if (data.toLowerCase(locale).contains(constraint.toString())) {
FilteredArrList.add(model);
}
}
// set the Filtered result to return
results.count = FilteredArrList.size();
results.values = FilteredArrList;
}
return results;
}
};
return filter;
}
}
My ViewHolder:
public class ChefSearchItem {
public String userName;
public String userAdmirers;
public String userUID;
public ChefSearchItem(String userName, String userAdmirers, String userUID) {
this.userName = userName;
this.userAdmirers = userAdmirers;
this.userUID = userUID;
}
}
More simpler way to filter out data is filter them locally
In your activity where your searchview is on submit call this method and pass the search string as parameter.
Make a temporary list which will consist of filterdata.
filter(String filter){
ArrayList<ChefSearchItem> filtereModelValues = new ArrayList<ChefSearchItem>();
for (ChefSearchItem chefSearchItem : <LIST YOU ARE SENDING TO ADAPTER>){
if(filter.toLowerCase().equals(chechefSearchItem.userUID.toLowerCase())
filtereModelValues.add(chefSearchItem );
}
//outside the for loop send the filtered list to adapter by creating method inside adapter name "filter" and pass filterList as parameter.
YOUR_ADAPTER.filter(filtereModelValues);
}
And in your adapter
public void filter(ArrayList<ChefSearchItem> filterModelValues){
modelValues = filterModelValues;
notifyDataChanged();
}
I have a Listview with a Custom BaseAdapter. I have already done the code for my MainActivity.java to apply SearchView. However, I have problem with the performFiltering method in my Adapter class due to the reason that I have a ImageView that would be shown on my ListView. The ImageView is originally in the form of String because I would like to get the image from an url in my Firebase Storage and then convert it to Image by using the Picasso library.
TL:DR. My problem is that everytime I perform a search, the url of the image stored in Firebase is showing up instead of the actual Image. Help is appreciated thanks.
Below is my Adapter Class:
public class GridAdapter extends BaseAdapter implements Filterable {
CustomFilter mCustomFilter;
ArrayList<GridItem> filterList;
private Context mContext;
private ArrayList<GridItem> gtem;
//Constructor
public GridAdapter(Context mContext, ArrayList<GridItem> gtem) {
this.filterList = gtem;
this.mContext = mContext;
this.gtem = gtem;
}
#Override
public int getCount() {
return gtem.size();
}
#Override
public Object getItem(int position) {
return gtem.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = View.inflate(mContext,R.layout.grid_item, null);
ImageView putPic = (ImageView)v.findViewById(R.id.imageHere);
TextView putTitle = (TextView)v.findViewById(R.id.titleHere);
TextView putPrice = (TextView)v.findViewById(R.id.per_price);
TextView putCountry = (TextView)v.findViewById(R.id.countryHere);
//
putCountry.setText("Country: " + gtem.get(position).getCountry());
putTitle.setText(gtem.get(position).getmTitleHere());
putCountry.setText(gtem.get(position).getCountry());
putPrice.setText("Price: " + "$" + gtem.get(position).getmPriceHere());
Picasso.with(mContext).load(gtem.get(position).getmImageView()).resize(450 , 500).into(putPic);
return v;
}
#Override
public Filter getFilter() {
//To-do Auto-generated method stub
if (mCustomFilter == null )
{
mCustomFilter = new CustomFilter();
}
return mCustomFilter;
}
//Inner Class
class CustomFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length()>0)
{
//Constraint to Upper
constraint = constraint.toString().toUpperCase();
ArrayList<GridItem> filters = new ArrayList<GridItem>();
//to get specific items
for (int i = 0; i<filterList.size(); i++)
{
if (filterList.get(i).getmTitleHere().toUpperCase().contains(constraint))
{
GridItem g = new GridItem(filterList.get(i).getmTitleHere() , filterList.get(i).getmPriceHere(), filterList.get(i).getmImageView()
, filterList.get(i).getCountry());
filters.add(g);
}
}
results.count = filters.size();
results.values = filters;
}else {
results.count = filterList.size();
results.values = filterList;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
gtem = (ArrayList<GridItem>) results.values;
notifyDataSetChanged();
}
}
}
I need help in implementing filterable interface for my list view items in a note app am currently working on. I have tried several ways but am not getting the expected result. For now it just does nothing after tying a search item.
I have implemented all the necessary methods in my adapter class and main activity.
I really need some help as i am quite new to this.Thanks in anticipation for positive replies.
// Note.java
public class Note implements Serializable {
private long mDateTime; //creation time of the note
private String mTitle; //title of the note
private String mContent; //content of the note
public Note(long dateInMillis, String title, String content) {
mDateTime = dateInMillis;
mTitle = title;
mContent = content;
}
public void setDateTime(long dateTime) {
mDateTime = dateTime;
}
public void setTitle(String title) {
mTitle = title;
}
public void setContent(String content) {
mContent = content;
}
public long getDateTime() {
return mDateTime;
}
}
public String getTitle() {
return mTitle;
}
public String getContent() {
return mContent;
}
}
// ArrayAdapter which implements Filterable
class NoteListAdapter extends ArrayAdapter<Note> implements Filterable{
List<Note> objects;
private List<Note> mStringFilterList;
Filter filter;
private static final int WRAP_CONTENT_LENGTH = 5;
public NoteListAdapter(Context context, int resource, List<Note> objects) {
super(context, resource, objects);
this.objects = objects;
this.mStringFilterList = objects;
}
#Override
public int getCount() {
return objects.size();
}
#Nullable
#Override
public Note getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public Filter getFilter() {
filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<Note> tempList=new ArrayList<Note>();
FilterResults results = new FilterResults();
if (constraint != null && objects != null) {
for(Note singleNote : objects) {
if( singleNote.getTitle().contains(constraint))
tempList.add(singleNote);
}
results.values = tempList;
results.count = tempList.size();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
objects = (ArrayList<Note>) results.values;
notifyDataSetChanged();
}
};
return filter;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = LayoutInflater.from(getContext())
.inflate(R.layout.list_component, parent, false);
}
return convertView;
}
}
// Main Activity
#Override
public boolean onQueryTextSubmit(String query) {
ArrayList<Note> notes = Utilities.getAllSavedNotes(getApplicationContext());
final NoteListAdapter na = new NoteListAdapter(this, R.layout.list_component, notes);
na.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
}
You're returning super.getFilter() instead of your filter you just created. And also, you're not filtering anything in the Filter performFiltering() method as you're adding every item to the results if the CharSequence has something and the adapter has items.
I would suggest something like that:
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<Note> tempList=new ArrayList<Note>();
FilterResults results = new FilterResults();
if (constraint != null && objects != null) {
for(Note singleNote : objects) {
if( singleNote.getTitle().contains(constraint)
tempList.add(singleNote);
}
results.values = tempList;
results.count = tempList.size();
}
return results;
}
EDITS:
Also, in the activity, inside the
#Override
public boolean onQueryTextSubmit(String query) {
ArrayList<Note> notes = Utilities.getAllSavedNotes(getApplicationContext());
final NoteListAdapter na = new NoteListAdapter(this, R.layout.list_component, notes);
na.getFilter().filter(query);
return false;
}
You're using a new adapter without setting it to the recyclerView/listView.
Try using the adapter you create inside the onCreate() of the activity or try using recyclerView/listView.setAdapter(na) after you change the adapter using the na.getFilter().filter(query);
EDITS2:
So, if you want your filter to be performed whenever the user input something move the code from the onQueryTextSubmit() to the onQueryTextChanged().
For the improvement you asked for (when the string is empty reload the full list) you have 2 ways:
First way:
#Override
public boolean onQueryTextChanged(String query) {
if (!query.equals("")) {
ArrayList<Note> notes = Utilities.getAllSavedNotes(getApplicationContext());
final NoteListAdapter na = new NoteListAdapter(this, R.layout.list_component, notes);
na.getFilter().filter(query);
} else {
ArrayList<Note> notes = Utilities.getAllSavedNotes(getApplicationContext());
final NoteListAdapter na = new NoteListAdapter(this, R.layout.list_component, notes);
}
return false;
}
The other way could be inside the performFiltering() method of the Filter interface implementation. You could also check if the string is empty there, and if so you need to return the full list, without creating a new support one in which you add elements only if certain condition are match.