I am using an autocomplete textview to filter by any letter.
The concept is working, but when I enter each letter, the application freezes or having a delay for some time.
Also while deleting too, the same happens. What am I doing wrong? is there anything am missing? My adapter class is added below.
Thanks in Advance.
public class ListAccNoAdapter extends ArrayAdapter<ListAccNo> {
Context context;
int resource, textViewResourceId;
List<ListAccNo> items, tempItems, suggestions;
public ListAccNoAdapter(Context context, int resource, int
textViewResourceId, List<ListAccNo> items) {
super(context, resource, textViewResourceId, items);
this.context = context;
this.resource = resource;
this.textViewResourceId = textViewResourceId;
this.items = items;
tempItems = new ArrayList<ListAccNo>(items); // this makes the
difference.
suggestions = new ArrayList<ListAccNo>();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.row_item, parent, false);
}
ListAccNo accnum = items.get(position);
if (accnum != null) {
TextView lblName = (TextView) view.findViewById(R.id.lbl_name);
if (lblName != null)
lblName.setText(accnum.getName());
}
return view;
}
#Override
public Filter getFilter() {
return nameFilter;
}
/**
* Custom Filter implementation for custom suggestions we provide.
*/
Filter nameFilter = new Filter() {
#Override
public CharSequence convertResultToString(Object resultValue) {
String str = ((ListAccNo) resultValue).getName();
return str;
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
if (constraint != null) {
List<ListAccNo> suggestions = new ArrayList<ListAccNo>();
FilterResults filterResults = new FilterResults();
for (ListAccNo accno : tempItems) {
if (accno.getName().toLowerCase().contains(constraint.toString().toLowerCase())) {
suggestions.add(accno);
}
}
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
} else {
return new FilterResults();
}
}
#Override
protected void publishResults(CharSequence constraint, FilterResults
results) {
List<ListAccNo> filterList = (ArrayList<ListAccNo>)
results.values;
if (results != null && results.count > 0) {
clear();
for (ListAccNo accnum : filterList) {
add(accnum);
notifyDataSetChanged();
}
}
}
};
}
I have used the AutoCompleteTextView and its working fine.
I have put the contents to be rendered in AutoCompleteTextView in String array first.
Then I've set the adapter contents in AutoCompleteTextView.
String[] arr=["a","b","c","d"]; // array contents
ArrayAdapter<String> adapter=new ArrayAdapter<String>
(this,android.R.layout.simple_dropdown_item_1line,arr);
AutoCompleteTextView autoCompleteTextView=
(AutoCompleteTextView)findViewById(R.id.autoCompleteTextView);
autoCompleteTextView.setThreshold(1);
autoCompleteTextView.setAdapter(adapter);
#Override
protected void publishResults(CharSequence constraint, FilterResults
results) {
List<ListAccNo> filterList = (ArrayList<ListAccNo>)
results.values;
if (results != null && results.count > 0) {
clear();
for (ListAccNo accnum : filterList) {
add(accnum);
//remove from here notifyDataSetChanged();
}
// put here notifyDataSetChanged();
}
}
};
Check your code, you are notifyDataSetChanged inside the loop, i think it will notify for each and every item thats why getting freezing, can you please check to remove this from inside loop and notify after completion of loop.I think it will work.
Problem Solved.
While setting the adapter in MainActivity, i have given a step to
autotextview.setThreshold(1);
Removing this line of code solved the issue.
Thanks Everyone for your help
Related
This is the code I am using for custom adapter for my autocomplete textview
I tried this solution link
This solution says that item count may be 0 but in my case item count is not 0.
It never goes to getView() method. I try it calling from Fragment, I tried calling it from Activity
I tried solution from this answer as well link but it doesn't work.
It never goes inside the getView() method.
public class BusCityListAdapter extends ArrayAdapter<BusCityList> {
private ArrayList<BusCityList> cityList;
private ArrayList<BusCityList> tempCityList;
private ArrayList<BusCityList> suggestionsList;
public BusCityListAdapter(Context context, ArrayList<BusCityList> objects) {
super(context, android.R.layout.simple_list_item_1, objects);
this.cityList = objects;
this.tempCityList = new ArrayList<BusCityList>(objects);
this.suggestionsList = new ArrayList<BusCityList>(objects);
}
#Override
public int getCount() {
System.out.println("Main List Size=="+cityList.size());
System.out.println("Temp List Size=="+tempCityList.size());
System.out.println("Suggestion List Size=="+suggestionsList.size());
return cityList.size();
}
#Override
public BusCityList getItem(int position) {
return cityList.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("Inside GetView");
BusCityList busCity = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.bus_city_name_layout, parent, false);
}
MyTextView bus_name_label = (MyTextView) convertView.findViewById(R.id.bus_name_label);
if (bus_name_label != null)
bus_name_label.setText(busCity.getCity_name());
// Now assign alternate color for rows
return convertView;
}
#Override
public Filter getFilter() {
return myFilter;
}
Filter myFilter = new Filter() {
#Override
public CharSequence convertResultToString(Object resultValue) {
BusCityList busCity = (BusCityList) resultValue;
return busCity.getCity_name();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
if (constraint != null) {
suggestionsList.clear();
for (BusCityList city : tempCityList) {
if (city.getCity_name().toLowerCase().startsWith(constraint.toString().toLowerCase())) {
suggestionsList.add(city);
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = suggestionsList;
filterResults.count = suggestionsList.size();
return filterResults;
} else {
return new FilterResults();
}
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
ArrayList<BusCityList> c = (ArrayList<BusCityList>) results.values;
if (results != null && results.count > 0) {
clear();
for (BusCityList city : c) {
add(city);
notifyDataSetChanged();
}
}
}
};
}
Here is the code where I am setting the adapter to AutoCompleteTextView
AutoCompleteTextView txtToWhere = (AutoCompleteTextView) v.findViewById(R.id.txtToWhere);
busCityListAdapter = new BusCityListAdapter(getActivity(), arrayList);
txtToWhere.setAdapter(busCityListAdapter);
busCityListAdapter.notifyDataSetChanged();
I am working on a basic android app that manages contacts. I am using a custom adapter and a custom listview. I have a class ContactItem that represents each contact. Every contact of the listview is a ContactItem instance. When I implemented my search view the app crashes. I followed that answer but each time I write inside the search to filter the listview, the app crashes.
I would appreciate having some supports because I have been trying to find a solution since February.
Here is my Adapter :
public class CustomAdapter extends ArrayAdapter<ContactItem> implements Filterable {
private Context context;
private ArrayList<ContactItem> arrayList;
public CustomAdapter(#NonNull Context context, int resource, ArrayList<ContactItem> arrayList) {
super(context, resource, arrayList);
this.context = context;
this.arrayList = arrayList;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = convertView;
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.customlist, parent, false);
TextView nom = (TextView) view.findViewById(R.id.nom);
String nomComplet = arrayList.get(position).getPrenom() + " " +arrayList.get(position).getNom();
nom.setText(nomComplet);
return view;
}
Filter myFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<ContactItem> templist = new ArrayList<ContactItem>();
//constraint is the text you want to filter your list with
//arraylist is the data set we will filter from
if(constraint != null && arrayList !=null){
int length = arrayList.size();
int i ;
String nomComplet;
Integer id;
String nom, prenom,phone,adresse,email;
for(i=0;i<length;i++){
nomComplet = arrayList.get(i).getNom()+" "+ arrayList.get(i).getPrenom();
if(nomComplet.toUpperCase().contains(constraint.toString().toUpperCase())){
ContactItem item = (ContactItem) arrayList.get(i);
templist.add(item);
}
}
filterResults.values = templist;
filterResults.count = templist.size();
}else {
filterResults.values = arrayList;
filterResults.count = arrayList.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
arrayList = (ArrayList<ContactItem>) results.values;
if(results.count>0){
notifyDataSetChanged();
}else{
notifyDataSetInvalidated();
}
}
};
#NonNull
#Override
public Filter getFilter() {
return myFilter;
}
}
Please check this one
Filter myFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<ContactItem> tempList=new ArrayList<ContactItem>();
//constraint is the result from text you want to filter against.
//objects is your data set you will filter from
if(constraint != null && objects!=null) {
int length=objects.size();
int i=0;
while(i<length){
ListTO item=objects.get(i);
//do whatever you wanna do here
//adding result set output array
tempList.add(item);
i++;
}
//following two lines is very important
//as publish result can only take FilterResults objects
filterResults.values = tempList;
filterResults.count = tempList.size();
}
return filterResults;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence contraint, FilterResults results) {
objects = (ArrayList<ContactItem>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
Last step,
#Override
public Filter getFilter() {
return myFilter;
}
what is wrong with my code? i am getting the entire list as suggestion in autocomplete text view.
public class ContactAdapter extends ArrayAdapter<String> {
List<ContactList> contactLists;
List<ContactList> suggestions;
LayoutInflater inflater;
public ContactAdapter(Activity context, int id, ArrayList list) {
super(context, id,list);
this.contactLists = list;
suggestions = new ArrayList<>();
inflater = (LayoutInflater.from(context));
}
private View getCustomView(final int position, View view, ViewGroup viewGroup){
view = inflater.inflate(R.layout.custom_contact_layout, null);
TextView name = (TextView)view.findViewById(R.id.textView);
TextView email = (TextView)view.findViewById(R.id.textView2);
name.setText(contactLists.get(position).getName());
email.setText(contactLists.get(position).getEmail());
return view;
}
#Override
public View getView(int position , View view , ViewGroup parent)
{
return getCustomView(position,view,parent);
}
#Override
public Filter getFilter() {
Filter nameFilter = new Filter() {
#Override
public CharSequence convertResultToString(Object result) {
return ((ContactList) result).getName();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
suggestions.clear();
for (int contactName = 0; contactName < contactLists.size(); contactName++) {
if (contactLists.get(contactName).getName().toLowerCase().startsWith(constraint.toString().toLowerCase())) {
suggestions.add(contactLists.get(contactName));
Log.d(">add>", contactLists.get(contactName).getName() + "");
}
}
filterResults.values = suggestions;
filterResults.count = suggestions.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count > 0) {
suggestions.clear();
suggestions = (List<ContactList>) results.values;
notifyDataSetChanged();
} else
notifyDataSetInvalidated();
}
};
return nameFilter;
}
}
Tell me how can i get only the filtered results as suggestions.In perform filter method only the filtered results get added. Why it is not getting reflected in publishResults method?
Change your code to:
Log.d(">>","called");
if(results.count >0){
suggestions.clear();
suggestions = (List<ContactList>) results.values;
notifyDataSetChanged();
}
else
notifyDataSetInvalidated();
}
My custom adapter for a AutoCompleteTextView always returns all items. results.count is always the correct size, that's why I'm wondering...
public class UniversityAdapter extends ArrayAdapter<University> implements Filterable {
List<University> items = new ArrayList<University>();
List<University> itemsAll = new ArrayList<University>();
private Context context;
int resource;
public UniversityAdapter(Context context, int resId, List<University> items) {
super(context, resId, items);
this.context = context;
this.resource = resId;
this.items = items;
itemsAll.addAll(this.items);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(resource, parent, false);
} else {
row = convertView;
}
University university = itemsAll.get(position);
TextView nameView = (TextView) row.findViewById(android.R.id.text1);
nameView.setText(university.getName());
return row;
}
#Override
public Filter getFilter() {
return new Filter() {
public String convertResultToString(Object resultValue) {
String str = ((University) (resultValue)).getName();
return str;
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
if (constraint != null) {
List<University> suggestions = new ArrayList<University>();
for (University university : itemsAll) {
if (university.getName().toLowerCase().startsWith(constraint.toString().toLowerCase())) {
suggestions.add(university);
}
}
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) {
if (results.count > 0) {
items = (ArrayList<University>) results.values;
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
}
}
I think this code is the culprit :
this.items = items;
itemsAll.addAll(this.items); //remove this, use only items
I suggest to remove itemsAll completely because items is enough.
Look at this code :
items = (ArrayList<University>) results.values;
notifyDataSetChanged();
You use items not itemsAll
UPDATE
And change (see my comments) :
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count > 0) {
List<University> universities= (ArrayList<University>) results.values;
items.clear(); //clear the old data
for(University univ : universities)
{
items.add(univ); //add each result
}
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
To get the desired result.
Good day, I have this custom adapter with a filterable interface implemented and am getting duplicate values in the resulting list.
SearchAutoCompleteAdapter.java
public class SearchAutoCompleteAdapter extends BaseAdapter implements Filterable {
private ArrayList<BaseAutocompleteItems> resultList;
List<BaseAutocompleteItems> filteredProducts;
private LayoutInflater layoutInflater;
private Context context;
private int layout;
SearchAutoCompleteAPI searchautocomplete = new SearchAutoCompleteAPI();
public SearchAutoCompleteAdapter(Context context, int resource) {
super();
this.context = context;
this.layout = resource;
filteredProducts = new ArrayList<BaseAutocompleteItems>();
resultList = new ArrayList<BaseAutocompleteItems>();
}
#Override
public int getCount() {
return resultList.size();
}
#Override
public Object getItem(int index) {
return resultList.get(index);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(layout, null);
}
TextView name = (TextView) convertView.findViewById(R.id.suggestion_text_id);
name.setText(resultList.get(position).getName());
return convertView;
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
List<BaseAutocompleteItems> tempfilteredProducts = new ArrayList<BaseAutocompleteItems
filteredProducts.clear();
if (constraint != null || constraint.length() > 0) {
tempfilteredProducts.clear();
tempfilteredProducts = searchautocomplete.autocomplete(constraint.toString()); //webservice call
} else {
tempfilteredProducts = new ArrayList<BaseAutocompleteItems>();
}
for (BaseAutocompleteItems items : tempfilteredProducts) {
if (items.getName().contains(constraint.toString())) {
filteredProducts.add(items);
}
}
filterResults.values = filteredProducts;
filterResults.count = filteredProducts.size();
return filterResults;
}
#Override
protected void publishResults (CharSequence constraint, FilterResults results){
resultList = (ArrayList<BaseAutocompleteItems>)results.values;
if(results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
;
return filter;
}
}
If I type "yell" and press backspace for "yel" or increase my char to "yello", I get the same result and thus the ArrayList ends up with duplicated items. I have tried clearing the lists before populating the list but nothing seems to work.
Nothing wrong with the code in the question. just a checklist for anyone first. make sure you call Clear() on the ArrayList being returned in the line.
tempfilteredProducts = searchautocomplete.autocomplete(constraint.toString()); //webservice call
from the API call first before populating the values from the webservice and sending it back to tempfilteredProducts(i.e before every api request). That way you avoid duplicate values from the autocompletetextview string as in my case in the question.
Try changing
if (items.getName().contains(constraint.toString()))
to
if (items.getName().startsWith(constraint.toString()))