This sounds easy but it has been hard for me. I have an autocomplete textview that shows user location address. I also implemented a places api to get addresses if user enters a different location other than their location. Everything is working like it is supposed to but the places result is still showing even when there is already an address. To reduce cost I would like to get address results only when the user enters an address. I made a global boolean and set it true when the text is changed like so:
autocomplete.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
isTextEntered = true; //to get autocomplete get results only after user enters text
}
#Override
public void afterTextChanged(Editable s) {
}
});
Then I check if the boolean is true when I set my adapter as such:
if (isTextEntered) {
autocomplete.setAdapter(new GooglePlacesAutocompleteAdapter(this, R.layout.search_results_list_item, R.id.tvSearchResultItem));
autocomplete.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final String selectedPlace = (String) parent.getItemAtPosition(position);
autocomplete.setText(selectedPlace);
}
});
}
But doing this in oncreate method of my activity simply blocks the autocomplete from showing any places hint results. How can I accomplish my goal here? As always any help is much appreciated.
This is my custom adapter class:
class GooglePlacesAutocompleteAdapter extends ArrayAdapter implements Filterable {
private ArrayList resultList;
//private ArrayList<HashMap<String, Place>> results = new ArrayList<>();
public GooglePlacesAutocompleteAdapter(Context context, int list, int textViewResourceId) {
super(context, list, textViewResourceId);
}
#Override
public int getCount() {
return resultList.size();
}
#Override
public String getItem(int index) {
return resultList.get(index).toString();
}
//#Override
//public HashMap<String, Place> getItem(int index) {return results.get(index);}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
// Retrieve the autocomplete results.
resultList = autocomplete(constraint.toString());
// Assign the data to the FilterResults
filterResults.values = resultList;
filterResults.count = resultList.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return filter;
}
}
Here is my idea to achieve this.
complete.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// 1. init autocomplete
// 2. show autocomplete
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// 1. get enter text
// 2. update the datasource of autocomplete adapter
}
#Override
public void afterTextChanged(Editable s) {
// hide the autocomplete
}
});
Hope it help
What I will suggest to you is just refactor it as a method like here
public void setSelectedPlace() {
autocomplete.setAdapter(new GooglePlacesAutocompleteAdapter(this, R.layout.search_results_list_item, R.id.tvSearchResultItem));
autocomplete.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final String selectedPlace = (String) parent.getItemAtPosition(position);
autocomplete.setText(selectedPlace);
}
});
}
And call it inside afterTextChanged method like here, and hide the autocomplete after that
#Override
public void afterTextChanged(Editable s) {
setSelectedPlace();
// hide the autocomplete
}
Related
I used RecyclerView and custom Adapter in my app ... adapter be implements Filterable for search. How to set high light search text ?
This my code for filterable in custom adapter :
private Filter filterResult = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<Moment> tempList = new ArrayList<>();
if (MOMENT_FILTER != null) {
if (TextUtils.isEmpty(constraint)) {
tempList = (ArrayList<Moment>) MOMENT_FILTER;
} else {
int length = MOMENT_LIST.size();
int i = 0;
while (i < length) {
Moment item = MOMENT_FILTER.get(i);
if (item.getMoment().contains(constraint))
tempList.add(item);
i++;
}
}
}
filterResults.values = tempList;
filterResults.count = tempList.size();
return filterResults;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
MOMENT_LIST = (ArrayList<Moment>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
}
}
};
#Override
public Filter getFilter() {
return filterResult;
}
And this my code in activity for text change (EditText) :
EDT_SEARCH.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s);
}
#Override
public void afterTextChanged(Editable s) {
}
});
result is OK with Sahil answer!
Have a reference of the searchText in your adapter
then in your OnBindViewHolder you can do as
String text = list.get(position).getText(); // Your getter Method
String htmlText = text.replace(searchText,"<font color='#c5c5c5'>"+searchText+"</font>");
// Only searchText would be displayed in a different color.
holder.textView.setText(Html.fromHtml(htmlText );
How to filter a RecyclerView with a SearchView(android.support.v7.widget.SearchView) which is not included in toolbar?
I want to filter the results in my recycler adapter using names which i am getting from api in a model.
I have set the recyclerview inside a fragment.
you can simply do it by searchview or edit text
for search view
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String text) {
return false;
}
#Override
public boolean onQueryTextChange(String text) {
filter(s.toString(),getCustomDeviceCheckItemsList());
return true;
}
});
private void filter(String text,ArrayList<CustomCheckItem> names) {
//new array list that will hold the filtered data
ArrayList<CustomCheckItem> filterdNames = new ArrayList<>();
//looping through existing elements
for (CustomCheckItem s : names) {
//if the existing elements contains the search input
if (s.getTitle().toLowerCase().contains(text.toLowerCase())) {
//adding the element to filtered list
filterdNames.add(s);
}
}
//calling a method of the adapter class and passing the filtered list
childAdapter.filterList(filterdNames);
}
and in adapter you have to write
public void filterList(ArrayList<CustomItem> filterdNames) {
this.list = filterdNames;
notifyDataSetChanged();
}
and if you want to do it by edit text then
search.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
filter(s.toString(),getCustomDeviceCheckItemsList());
}
});
I have custom listview using simple adapter, Currently I have issue regarding filter that I have custom list data with numbers and characters in listview.
If I enter name then its give one blank space the filter results gets disappear.
I have list data like name then number for example : NAME 123, Whenever I enter name then gives space in that edit text then results are gone and list-view gets disappears.
I have tried this on below link but they used Array adapter, So my question is is it possible only in Array adapter or I can used simple adapter?
Android listview edittext filter space button?
If yes then how can I implement, kindly help. Advance thank you.
try this way
searchView.setOnEditorActionListener(new EditText.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
return true;
}
});
addTextChangeListener();
now create method addTextChangeListener
private void addTextChangeListener() {
searchView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence query, int start, int before, int count) {
query = query.toString().trim().toLowerCase();
final ArrayList<CityDataModel> filteredList = new ArrayList<>();
final CharSequence finalQuery = query;
new Thread(new Runnable() {
#Override
public void run() {
// Clear the filter list
filteredList.clear();
// If there is no search value, then add all original list items to filter list
if (TextUtils.isEmpty(finalQuery)) {
filteredList.addAll(cities);
} else {
// Iterate in the original List and add it to filter list...
for (CityDataModel item : cities) {
if (item.getCity_name().toLowerCase().contains(finalQuery.toString().toLowerCase())
) {
// Adding Matched items
filteredList.add(item);
}
}
}
// Set on UI Thread
((Activity) context).runOnUiThread(new Runnable() {
#Override
public void run() {
// Notify the List that the DataSet has changed...
adapter = new SearchCityAdapter(SearchCityClass.this, filteredList);
recyclerSearchCity.setAdapter(adapter);
}
});
}
}).start();
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
You can use any Adapter, you can just implements your adapter with android.widget.Filterable
Example Adapter,
public class AppAdapter extends RecyclerView.Adapter<AppHolder> implements Filterable {
public static final String TAG = AppAdapter.class.getSimpleName();
private ArrayList<App> mApps = new ArrayList<>();
private List<App> mCurrentItmCopy = new ArrayList<>();
private String currentFilter;
private MyArrayFilter mFilter;
#Override
public AppHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View receiverView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.layout_row_apps, parent, false);
return new AppHolder(receiverView);
}
#Override
public void onBindViewHolder(final AppHolder holder, int position) {
final App data = mApps.get(position);
}
#Override
public int getItemCount() {
return mApps.size();
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new MyArrayFilter();
}
return mFilter;
}
private class MyArrayFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mCurrentItmCopy == null || (mCurrentItmCopy.size() == 0)) {
mCurrentItmCopy = new ArrayList<App>(mApps);
}
ArrayList<App> newValues = new ArrayList<App>();
if (prefix != null && !TextUtils.isEmpty(prefix.toString())) {
String prefixString = prefix.toString().toLowerCase();
for (App value : mCurrentItmCopy) {
String label = value.getLabel().toLowerCase();
if ((label.contains(prefixString)) && !newValues.contains(value)) {
newValues.add(value);
}
}
results.values = newValues;
results.count = newValues.size();
} else {
results.values = new ArrayList<App>(mCurrentItmCopy);
results.count = mCurrentItmCopy.size();
mCurrentItmCopy.clear();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
currentFilter = constraint.toString();
if (results.count > 0) {
mApps.clear();
addAll((ArrayList<App>) results.values);
} else {
mApps.clear();
notifyDataSetChanged();
}
}
}
public void addAll(List<App> items) {
if (items != null) {
mApps.addAll(items);
}
notifyDataSetChanged();
}
}
In the above Adapter instead of App, you can use your object.
You can call from your activity or fragment like this,
mAdapter.getFilter().filter(newText);
I am working on the project in which user can search data. For that, I have implemented AutoCompleteTextView.
autoComplete.setAdapter(new ArrayAdapter<String>(CheckRiskActivity.this,
R.layout.auto_text_row, druglist));
autoComplete.setThreshold(1);
//druglist is my arraylist
Text change listener is as below:
autoComplete.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
// here I want to get the size of filtered array list every time when the user adds any character.
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
Explanation: If my initial array size is 100 and if the user types 'a', then I want to get the size of filtered array.
Note: I have tried autoComplete.getAdapter().getCount(); but it gives the actual result after adding one more character.
You cannot get correct filtered items' count in TextWatcher, because filtering usually takes longer time than TextWatcher event listeners. Therefore you get incorrect autoComplete.getAdapter().getCount() in afterTextChanged(). I would recommend to use custom listener which will be called every time when filtered items are changed.
I will provide 2 similar approaches: using separate classes and using only 1 class.
APPROACH 1:
Your adapter should look like:
import android.content.Context;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import java.util.ArrayList;
import java.util.List;
public class AutoCompleteAdapter extends ArrayAdapter
{
private List<String> tempItems;
private List<String> suggestions;
private FilterListeners filterListeners;
public AutoCompleteAdapter(Context context, int resource, List<String> items)
{
super(context, resource, 0, items);
tempItems = new ArrayList<>(items);
suggestions = new ArrayList<>();
}
public void setFilterListeners(FilterListeners filterFinishedListener)
{
filterListeners = filterFinishedListener;
}
#Override
public Filter getFilter()
{
return nameFilter;
}
Filter nameFilter = new Filter()
{
#Override
protected FilterResults performFiltering(CharSequence constraint)
{
if (constraint != null)
{
suggestions.clear();
for (String names : tempItems)
{
if (names.toLowerCase().startsWith(constraint.toString().toLowerCase()))
{
suggestions.add(names);
}
}
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<String> filterList = (ArrayList<String>) results.values;
if (filterListeners != null && filterList!= null)
filterListeners.filteringFinished(filterList.size());
if (results != null && results.count > 0)
{
clear();
for (String item : filterList)
{
add(item);
notifyDataSetChanged();
}
}
}
};
}
An interface which is used to inform you when filtering will be finished:
public interface FilterListeners
{
void filteringFinished(int filteredItemsCount);
}
And you can use it:
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.AutoCompleteTextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity implements FilterListeners
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AutoCompleteTextView autoComplete = (AutoCompleteTextView) findViewById(R.id.autoComplete);
autoComplete.setThreshold(1);
List<String> stringList = new ArrayList<>();
stringList.add("Black");
stringList.add("White");
stringList.add("Yellow");
stringList.add("Blue");
stringList.add("Brown");
final AutoCompleteAdapter adapter = new AutoCompleteAdapter(this, android.R.layout.simple_list_item_1, stringList);
adapter.setFilterListeners(this);
autoComplete.setAdapter(adapter);
}
#Override
public void filteringFinished(int filteredItemsCount)
{
Log.i("LOG_TAG", " filteringFinished count = " + filteredItemsCount);
}
}
APPROACH 2:
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Filter;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final AutoCompleteTextView autoComplete = (AutoCompleteTextView) findViewById(R.id.autoComplete);
autoComplete.setThreshold(1);
final List<String> stringList = new ArrayList<>();
stringList.add("Black");
stringList.add("White");
stringList.add("Yellow");
stringList.add("Blue");
stringList.add("Brown");
final ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, stringList)
{
private List<String> tempItems = stringList;
private List<String> suggestions = new ArrayList<>();
#Override
public Filter getFilter()
{
return nameFilter;
}
Filter nameFilter = new Filter()
{
#Override
protected FilterResults performFiltering(CharSequence constraint)
{
if (constraint != null)
{
suggestions.clear();
for (String names : tempItems)
{
if (names.toLowerCase().startsWith(constraint.toString().toLowerCase()))
{
suggestions.add(names);
}
}
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<String> filterList = (ArrayList<String>) results.values;
filteringFinished(filterList.size());
if (results != null && results.count > 0)
{
clear();
for (String item : filterList)
{
add(item);
notifyDataSetChanged();
}
}
}
};
};
autoComplete.setAdapter(arrayAdapter);
}
private void filteringFinished(int filteredItemsCount)
{
Log.i("LOG_TAG", " filteringFinished count = " + filteredItemsCount);
}
}
filteringFinished() method will be called when you enter something to an autocomplete input field and it gets filtered.
UPDATE (Trie Search):
I have created a Github project with a simple example of using Trie search algorithm to increase autocomplete performance very much.
https://github.com/saqada/android-AutoCompleteWithTrie
according to Ayaz Alifov answer you cannot get correct filtered items' count in TextWatcher, because filtering usually takes longer time than TextWatcher event listeners.
but i have done a trick with a timerTask. so the TextWatcher would execute after counting.
editText.addTextChangedListener(
new TextWatcher() {
#Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
#Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
private Timer timer=new Timer();
private final long DELAY = 1000; // milliseconds
#Override
public void afterTextChanged(final Editable s) {
timer.cancel();
timer = new Timer();
timer.schedule(
new TimerTask() {
#Override
public void run() {
// adapter.getCount() will give you the correct item's counts
Log.d(TAG, "run: afterTextChanged " + adapter.getCount());
}
},
DELAY
);
}
}
);
Edited: 5/Sep/2019
you can also get items count with the help of setting a registerDataSetObserver.
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
Log.d(TAG, "onChanged: " + adapter.getCount());
}
});
in this way the onChanged() will call every time text change. But if the suggestion list becomes empty, it will not be called.
Basically, we have to implement Filterable at Adapter class
public class DrugListAdapter extends BaseAdapter implements
Filterable {
Context context;
LayoutInflater inflater;
drugsFilter drugsFilter;
List<Drug> drugList = new ArrayList<>();
private List<Drug> drugListOrig;
public DrugListAdapter(Context context,
List<Drug> drugList) {
super();
this.context = context;
this.drugList = drugList;
this.drugListOrig = new ArrayList<>(
drugList);
inflater = LayoutInflater.from(context);
}
public void resetData() {
drugList = drugListOrig;
}
#Override
public int getCount() {
return drugList.size();
}
#Override
public Drug getItem(int position) {
return drugList.get(position);
}
#Override
public long getItemId(int id) {
return id;
}
private class ViewHolder {
TextView mVendorName;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
ViewHolder viewHolder;
Drug item = drugList.get(position);
if (view == null) {
viewHolder = new ViewHolder();
view = inflater.inflate(R.layout.item_drug,
parent, false);
viewHolder.mVendorName = (TextView) view
.findViewById(R.id.item_drug_drug_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.mVendorName.setText(item.getDrug_name());
return view;
}
#Override
public Filter getFilter() {
if (drugsFilter == null) {
drugsFilter = new DrugsFilter();
}
return drugsFilter;
}
public class DrugsFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// We implement here the filter logic
if (constraint == null || constraint.length() == 0) {
// No filter implemented we return all the list
results.values = drugListOrig;
results.count = drugListOrig.size();
} else {
// We perform filtering operation
List<Drug> sList = new ArrayList<>();
for (Drug p : drugList) {
if (p.getDrug_name().toUpperCase()
.startsWith(constraint.toString().toUpperCase()))
sList.add(p);
}
results.values = sList;
results.count = sList.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (results.count == 0)
notifyDataSetInvalidated();
else {
drugList = (List<Drug>) results.values;
notifyDataSetChanged();
}
}
}
}
This part is for EditText and TextWatcher
String m;
mDrugEditText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (count < before) {
adapter.resetData();
adapter.notifyDataSetChanged();
}
adapter.getFilter().filter(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int before, int count) {
if (s.length() == 0 || s.length() == 1) {
mDrugEditText.invalidate();
}
if (s.length() == 3) {
if (mDrugEditText
.isPerformingCompletion()) {
return;
}
adapter.resetData();
adapter.notifyDataSetChanged();
}
}
#Override
public void afterTextChanged(Editable s) {
m = s.toString();
adapter.getFilter().filter(s.toString());
}
});
I am assuming that you have gone through the basic search options available in android/java and you are not satisfied with the results.
If you do not want to go through entire list at every text change, the only way is to implement a datastructure which does that.
The obvious solution will be trie.read this to get an idea about trie
Now, this works on the concept of pre-processing the data before searching. Since you have limited elements - it will not take much time, and you can possibly do it when the page loads.
Steps -
- Process and index all elements on load. Put indexes on a k-ary tree (it will be 32-ary, every character will be an alphabet).
- on text changed - traverse to the node and get the count. It will take O(1).
I believe this is the fastest you can go.
The above will work best if you have words indexed or if you just have to do startswith.
Sa Qada's answer is a very good approach, However, my below answer gave me better performance in my case.
autoCompleteTextViewCheckRisk.setAdapter(new ArrayAdapter<String>
(CheckRiskActivity.this, R.layout.auto_text_row, druglist));
//druglist is the Arraylist of String.
autoCompleteTextViewCheckRisk.setThreshold(1);
Text Change Listener:
autoCompleteTextViewCheckRisk.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
filter(druglist, s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
Method for Filter:
private void filter(ArrayList<String> originalArrayList, String query) {
query = query.toLowerCase();
filteredArrayList.clear();
//filtered arraylist is also Arraylist of String, Just declared as global
for (String itemName : originalArrayList) {
final String text = itemName.toLowerCase();
if (text.startsWith(query)) {
filteredArrayList.add(itemName);
}
}
if (filteredArrayList.size() == 0) {
Log.i(TAG, "filter: No data found");
}
}
I have a ListView that contains an EditText to filter list result. Everything is working well during this phase.
My problem is after clicking an item in the list and then go back to the ListView, the item in the list is gone, most probably the because EditText contains an empty space after back button is pressed. Why is this so?
I've put a Log inside onTextChanged to see what character is being put when the back button is pressed. It's just blank. I'm not sure why this listener adds an empty space and filter the result after back button is pressed.
Here is the code in ListFragment:
public class CategoryFragment extends ListFragment {
...
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// filter result
etFilterCategory.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
// Log.d(TAG, "ontextchanged= " + charSequence);
va.getFilter().filter(charSequence);
}
#Override
public void afterTextChanged(Editable editable) {
}
});
}
}
The BaseAdapter implementing Filterable:
public class CategoryAdapter extends ArrayAdapter<CategoryModel> implements
Filterable {
...
#Override
public Filter getFilter() {
return mFilter;
}
private class ItemFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
final ArrayList<CategoryModel> list = originalData;
int count = list.size();
final ArrayList<CategoryModel> nlist = new ArrayList<CategoryModel>(count);
String filterableString;
for (int i = 0; i < count; i++) {
filterableString = list.get(i).getName();
if(filterableString.toLowerCase().contains(filterString)) {
// add the whole custom row
nlist.add(list.get(i));
}
}
results.values = nlist;
results.count = nlist.size();
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
arrCategory = (ArrayList<CategoryModel>) results.values;
notifyDataSetChanged();
}
}
}
How do I NOT make the ListView item filtered after every back button pressed?
EDIT:
After back button is pressed, the only way to make the ListView visible is to add a space into the EditText and remove it. That will show the previous list. What did I missed?
you may be re-creating your listAdapter object, this will nullify the previously created listAdapter.
Your call of textwatcher is pointing to older listadapter where in onResume/OnCreateView event your new instance of listadapter is generated.
I solved my problem by declaring listadapter object as member in my fragment and checking it in onResume method as follow
#Override
public void onResume() {
super.onResume();
if (news == null) {
if(CommonFun.isInternetOn(activity))
new NewsRetrivalTask().execute();
else
ToastMsg.showToast(activity, Msg.alertInternetMsg);
} else {
newsListAdapter = new NewsListAdapter(getActivity(), news);
lv.setAdapter(newsListAdapter);
lv.setOnItemClickListener(MAP_FragmentChatRoom.this);
lv.setVisibility(View.VISIBLE);
tvNoRecord.setVisibility(View.GONE);
}
}
and textwatcher in onCreateView method
etSearch.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) { }
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
public void onTextChanged(CharSequence s, int start, int before, int count) {
newsListAdapter.getFilter().filter(s);
}
});