I am facing a problem of my filtered ListView not updating.
In my application there is a custom ListView which has a two TextView and one ImageView as a row elements.
The filter works fine but my custom ListView is not updated in publishResults().
#Override
protected FilterResults performFiltering(CharSequence constraint)
{
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() <= 0) {
results.count = ListAdapter.this.mStringFilterList.size();
results.values = ListAdapter.this.mStringFilterList;
} else {
ArrayList<Ezomart> filterList = new ArrayList();
for (int i = 0; i < ListAdapter.this.mStringFilterList.size(); i++) {
if (((Ezomart) ListAdapter.this.mStringFilterList.get(i)).getTitle().toUpperCase().contains(constraint.toString().toUpperCase())) {
Ezomart country = new Ezomart();
country.setTitle(((Ezomart)ListAdapter.this.mStringFilterList.get(i)).getTitle());
Log.d("SRI",mStringFilterList.get(i).getTitle());
country.setSubCategory(((Ezomart) ListAdapter.this.mStringFilterList.get(i)).getSubCategory());
country.setArea(((Ezomart) ListAdapter.this.mStringFilterList.get(i)).getArea());
country.setThumbnailUrl(((Ezomart) ListAdapter.this.mStringFilterList.get(i)).getThumbnailUrl());
country.setNumber(((Ezomart) ListAdapter.this.mStringFilterList.get(i)).getNumber());
filterList.add(country);
}
}
results.count = filterList.size();
results.values = filterList;
}
return results;
}
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
ListAdapter.this.ezoItems = (List<Ezomart>) filterResults.values;
if (filterResults.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
I found the answer by following the link below. Thanks to MBH.
I had to add this code in my fragment.
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// What i have added is this
setHasOptionsMenu(true);
}
For reference please follow the link:
Android search with Fragments
Related
Actually i have a filter method in my recyclerView adapter and when there is no item in the arraylist the recyclerView just hide and i would to show an alert instead of just showing no item.
How can i detect when filter return no item found?
Here is the filter method from adapter
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oReturn = new FilterResults();
final ArrayList<ItemModel> results = new ArrayList<>();
if (mFilteredList == null)
mFilteredList = new ArrayList<>(variantiConstructors);
if (constraint != null && constraint.length() > 0) {
if (mFilteredList != null && mFilteredList.size() > 0) {
for (final ItemModel cd : mFilteredList) {
if (cd.getCodiceArticolo().toLowerCase()
.contains(constraint.toString().toLowerCase()))
results.add(cd);
}
}
oReturn.values = results;
oReturn.count = results.size(); //newly Aded by ZA
} else {
oReturn.values = mFilteredList;
oReturn.count = mFilteredList.size(); //newly added by ZA
}
return oReturn;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(final CharSequence constraint,
FilterResults results) {
variantiConstructors = new ArrayList<>((ArrayList<ItemModel>) results.values);
notifyDataSetChanged();
}
};
}
And here is where i'm calling it
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
itemAdapter.getFilter().filter(edtSearch.getText().toString().toLowerCase());
Log.e("COUNT",String.valueOf(itemAdapter.getItemCount()));
}
instead of checking for result.values or result.count i had to check if variantiConstructor.isEmpty as result was returning in any case true.
So in the adapter i'm using now the following code to show an alert when there are no items found
protected void publishResults(final CharSequence constraint,
FilterResults results) {
variantiConstructors = new ArrayList<>((ArrayList<ItemModel>) results.values);
if(variantiConstructors.isEmpty()){
Alerts.alertError("NO","",mContext);
}
notifyDataSetChanged();
}
I want to search in recyclerview.
I write the Filter method in recyclerview adapter like this:
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oReturn = new FilterResults();
final ArrayList<Info_Filter> results = new ArrayList<Info_Filter>();
if (orig == null)
orig = items;
if (constraint != null) {
if (orig != null & orig.size() > 0) {
for (final Info_Filter g : orig) {
if (g.getName().toLowerCase().contains(constraint.toString()))
results.add(g);
}
}
oReturn.values = results;
}
return oReturn;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
items = (ArrayList<Info_Filter>) results.values;
notifyDataSetChanged();
}
};
}
Its ok, now I have another recycler that work with this adapter and this data model. Each one have a edit text to search. when I write something in first edit text, recyclerview number 2 changes.
How I can search for both recyclers?
First, create a class which extends Filter
public class NewFilter extends Filter {
private recyclerAdapter adapter;
private ArrayList<Info_Filter> filterList;
NewFilter(ArrayList<Info_Filter> filterList, recyclerAdapter adapter) {
this.adapter = adapter;
this.filterList = filterList;
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
constraint = constraint.toString().toUpperCase();
ArrayList<Info_Filter> filteredInfo = new ArrayList<>();
for (int i = 0; i < filterList.size(); i++) {
if (filterList.get(i).getName().toLowerCase().contains(constraint)) {
filteredInfo.add(filterList.get(i));
}
}
results.count = filteredInfo.size();
results.values = filteredInfo;
} else {
results.count = filterList.size();
results.values = filterList;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
adapter.mDataSet = (ArrayList<Info_Filter>) results.values;
adapter.notifyDataSetChanged();
}
}
Now implement the Filterable interface to your RecyclerView Adapter and override the getFilter() method.
#Override
public Filter getFilter() {
if (filter == null) {
filter = new NewFilter(filterMDataSet, this);
}
return filter;
}
filterMDataSet can be a copy of the ArrayList that you pass to the adapter when setting the adapter to you recyclerview. You could create another ArrayList in the adapter and initialize it in the constructor with the same data as the main ArrayList.
Now its tike to filter the results using a text. You can run this code with the text that you need to filter.
if (recyclerView.getAdapter() != null) {
((YourAdapter) yourAdapter).getFilter().filter(text_to_filter);
}
Check if this works?
I am using a autocompletetextview with custom adapter in android. it works fine. But when i click backspace to clear selected item from autocomplete textview it freezes, or there is a delay in deleting. How can i overcome this ? My filter codes are given below
#Override
protected FilterResults performFiltering(CharSequence constraint) {
if (constraint != null) {
suggestions.clear();
FilterResults filterResults = new FilterResults();
for (Names people : tempItems) {
if(people.getName().toLowerCase().contains(constraint.toString()
.toLowerCase())) {
suggestions.add(people);
}
}
// FilterResults filterResults = new FilterResults();
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
} else {
return new FilterResults();
}
}
#Override
protected void publishResults(CharSequence constraint, FilterResults
results) {
List<Names> filterList = (ArrayList<Names>) results.values;
if (results != null && results.count > 0) {
clear();
for (Names people : filterList) {
add(people);
notifyDataSetChanged();
}
}
}
};
What am i doing wrong ? Thanks in Advance.
Modify you filter according to the below code. You are notifying the adapter inside the loop, it should be notified once the whole list is added into the other list i.e. outside the loop.
// This is my whole adapter and works like a charm and about the updation on the UI thread, yes I am notifying the adapter on the UI thread.
public class SuburbSuggestionsAdapter extends ArrayAdapter<String> implements Filterable {
protected static final String TAG = "SuggestionAdapter";
private List<String> suggestions;
private Context context;
private List<String> SuburbList = new ArrayList<>();
public SuburbSuggestionsAdapter(Context context) {
super(context, android.R.layout.simple_dropdown_item_1line);
suggestions = new ArrayList<String>();
this.context = context;
}
#Override
public int getCount() {
return (null != suggestions ? suggestions.size() : 0);
}
#Override
public String getItem(int index) {
return suggestions.get(index);
}
#Override
public Filter getFilter() {
Filter myFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if(!TextUtils.isEmpty(constraint)){
WebServiceHandler.hitFetchSuburbList(context, constraint.toString(), new CallbackRest() {
#Override
public void onDone(String response) {
if(SuburbList.size()!=0){
SuburbList.clear();
}
try {
JSONArray jsonArray = new JSONArray(response);
for(int i=0; i<jsonArray.length(); i++){
SuburbList.add(jsonArray.get(i).toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
// A class that queries a web API, parses the data and
// returns an ArrayList<GoEuroGetSet>
List<String> new_suggestions = SuburbList;
suggestions.clear();
for (int i=0;i<new_suggestions.size();i++) {
suggestions.add(new_suggestions.get(i));
}
// Now assign the values and count to the FilterResults
filterResults.values = suggestions;
filterResults.count = suggestions.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence contraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return myFilter;
}
}
I have this class:
public class MyAdapter extends BaseAdapter implements Filterable
and override this method
#Override
public Filter getFilter()
{
return new Filter()
{
#Override
protected FilterResults performFiltering(CharSequence charSequence)
{
FilterResults results = new FilterResults();
if(charSequence == null || charSequence.length() == 0)
{
results.values = originalData;
results.count = originalData.size();
}
else
{
ArrayList<Map<String,String>> filterResultsData = new ArrayList<Map<String,String>>();
results.values = filterResultsData;
results.count = filterResultsData.size();
}
return results;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults)
{
filteredData = (ArrayList<Map<String,String>>)filterResults.values;
if (filterResults.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
}
As you can see in the above code, in the performFiltering method, in the else block, I've done nothing to populate the filterResultsData. Why? Because if I do any operation, it will results in app crashing when i try to filter the listview.
Means, all is well, I can run the apps in emulator, the listview appears, but as soon as I'm typing a word in the textbox (to filter), the app crash. (No error code or any other message at the console)
Please help. I don't know what went wrong.
All I want to do is displaying a CheckBox at each result of the AutoCompleteTextView's results (which are strings).
I wrote an custom Array Adapter which implements Filterable. I added a simple Filter wich gets called (I checked that) and returns the expected results. However the displayed results are completely different ones.
Here is my Filter-Code:
private class MyFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence constraint)
{
FilterResults results = new FilterResults();
if ((constraint == null) || (constraint.length() == 0))
{
synchronized (mLock)
{
ArrayList<String> list = new ArrayList<String>();
results.values = list;
results.count = list.size();
}
}
else
{
String constr = constraint.toString().toLowerCase();
final ArrayList<String> newItems = new ArrayList<String>();
for (String temp : items)
{
if (temp.toLowerCase().startsWith((constr)))
{
newItems.add(temp);
}
}
results.values = newItems;
results.count = newItems.size();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint,
FilterResults results)
{
if (results.count > 0)
{
notifyDataSetChanged();
}
else
{
notifyDataSetInvalidated();
}
}
}
Do I miss something?
Thank you!
I forgot to set my results as the new items of the adapter.