TextWatcher that changes two ListViews with two custom ArrayAdapters - android

I have the code for TextWatcher that changes 2 different listViews using 2 different ArrayAdapters.
private TextWatcher createAndReturnTextWatcher()
{
final List<String> list = dbExtractor.getDataForSearchAdapters();
adapterForSearch = new MyAdapter(this, R.layout.list_item2, R.id.product_name,
list);
adapter = new ArrayAdapter(this, R.layout.list_item2, R.id.product_name,
dbExtractor.getDataForSearchAdapters());
TextWatcher watcher1;
watcher1 = new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
if (cs.length() == 0) {
lv.setAdapter(null);
lv2.setAdapter(null);
dc.clickedOnce = true;
dc.decrement();
dc.checkDimCounter();
} else {
lv.setAdapter(adapterForSearch);
adapterForSearch.getFilter().filter(cs);
lv2.setAdapter(adapter);
adapter.getFilter().filter(cs);
if (dc.clickedOnce) {
dc.increment();
dc.checkDimCounter();
dc.clickedOnce = false;
}
}
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
#Override
public void afterTextChanged(Editable arg0) {
}
};
return watcher1;
}
The question is:
Why this works properly when I use one standart ArrayAdapter class, and one custom ArrayAdapter class, but it doesn't work if I try to use both custom ArrayAdapters. This just changes both listViews like they both use one of custom adapters?
Thanks in advance!
MY CUSTOM ADAPTERS
1st
public class MyTurkishAdapter extends ArrayAdapter {
protected Filter myTurkFilter;
protected List<String> mObjects;
protected List<String> mOriginalValues;
public MyTurkishAdapter(Context context, int resource, int textViewResourceId, List objects) {
super(context, resource, textViewResourceId, objects);
myTurkFilter = new MyTurkFilter();
mObjects = objects;
}
#Override
public Filter getFilter() {
return myTurkFilter;
}
private class MyTurkFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
{
mOriginalValues = new ArrayList<String>(mObjects);
}
}
if (prefix == null || prefix.length() == 0) {
ArrayList<String> list;
{
list = new ArrayList<>(mOriginalValues);
}
results.values = list;
results.count = list.size();
} else {
java.lang.String prefixString = prefix.toString().toLowerCase();
ArrayList<String> values;
{
values = new ArrayList<>(mOriginalValues);
}
final int count = values.size();
final ArrayList<String> newValues = new ArrayList<String>();
for (int i = 0; i < count; i++) {
final String value = values.get(i);
final java.lang.String valueText = value.toLowerCase();
if (valueText.startsWith(prefixString)) {
newValues.add(reverse(value));
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mObjects.clear();
mObjects.addAll((List<String>) results.values);
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
private java.lang.String reverse(java.lang.String couples)
{
java.lang.String[] arr = couples.split(" — ");
return arr[1]+ " — " + arr[0];
}
}
2nd
public class MyAdapter extends ArrayAdapter {
protected Filter filter;
protected List<String> mObjects;
protected List<String> mOriginalValues;
public MyAdapter(Context context, int resource, int textViewResourceId, List<String> objects) {
super(context, resource, textViewResourceId, objects);
filter = new MyFilter();
mObjects = objects;
}
#Override
public Filter getFilter() {
return filter;
}
private class MyFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
{
mOriginalValues = new ArrayList<String>(mObjects);
}
}
if (prefix == null || prefix.length() == 0) {
ArrayList<String> list;
{
list = new ArrayList<String>(mOriginalValues);
}
results.values = list;
results.count = list.size();
} else {
java.lang.String prefixString = prefix.toString().toLowerCase();
ArrayList<String> values;
{
values = new ArrayList<String>(mOriginalValues);
}
final int count = values.size();
final ArrayList<String> newValues = new ArrayList<String>();
//DictionaryActivity2.turkish.clear();
for (int i = 0; i < count; i++) {
final String value = values.get(i);
final java.lang.String valueText = value.toString().toLowerCase();
if (valueText.startsWith(prefixString)) {
newValues.add(value);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mObjects.clear();
mObjects.addAll((List<String>) results.values);
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
P.S. They have just one line difference. I know about Template Method pattern and will implement this right after I'll find the answer for this question :)

Related

Make input from Single EditText show different output in different views

I have an EditText field and two ListViews.
I want to input data in EditText and get two different results shown on ListViews.
For example 1st ListView shows words that starts with input and second ListView shows words that contains my input.
For this I have 2 custom ArrayAdapters. Separately they work well, but if I try use them togethe in a TextWatcher it starts to bug a lot. What's an issue with this? And what is the best way to implement functionality I've described?
Thanks in advance.
This is the code of my TextWatcher:
TextWatcher watcher1;
watcher1 = new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
if (cs.length() == 0) {
//lv and lv2 are my ListViews
lv.setAdapter(null);
lv2.setAdapter(null);
} else {
//lv and lv2 are my ListViews
lv.setAdapter(adapterForSearch);
lv2.setAdapter(adapterForTurkishSearch);
adapterForSearch.getFilter().filter(cs);
adapterForTurkishSearch.getFilter().filter(cs);
}
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
#Override
public void afterTextChanged(Editable arg0) {
}
};
//inputSearch in my EditText object
inputSearch.addTextChangedListener(watcher1);
UPD:
This is my Adapter + filter code.
public class MyAdapter<String> extends ArrayAdapter<String> {
protected Filter filter;
protected List<String> mObjects;
protected List<String> mOriginalValues;
protected List<String> tempList;
public MyAdapter(Context context, int resource, int textViewResourceId, List<String> objects) {
super(context, resource, textViewResourceId, (List<String>) objects);
filter = new MyFilter();
mObjects = (List<String>) objects;
tempList = new ArrayList<>();
//mOriginalValues = (List<String>) objects;
}
#Override
public Filter getFilter() {
return filter;
}
private class MyFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
{
mOriginalValues = new ArrayList<String>(mObjects);
}
}
if (prefix == null || prefix.length() == 0) {
ArrayList<String> list;
{
list = new ArrayList<String>(mOriginalValues);
}
results.values = list;
results.count = list.size();
} else {
java.lang.String prefixString = prefix.toString().toLowerCase();
ArrayList<String> values;
{
values = new ArrayList<String>(mOriginalValues);
}
final int count = values.size();
final ArrayList<String> newValues = new ArrayList<String>();
for (int i = 0; i < count; i++) {
final String value = values.get(i);
final java.lang.String valueText = value.toString().toLowerCase();
// First match against the whole, non-splitted value
if (valueText.startsWith(prefixString)) {
newValues.add(value);
} else {
/*final java.lang.String[] words = valueText.split(" ");
final int wordCount = words.length;
// Start at index 0, in case valueText starts with space(s)
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefixString)) {
newValues.add(value);
break;
}
}*/
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//mObjects = (List<String>) results.values;
mObjects.clear();
mObjects.addAll((List<String>) results.values);
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}

Incompatible type in Android AutoCompleteTextView

I'm trying to add multiple values in AutoCompleteTextView from SQlite Database in Android.But it shows incompatible type for this method =
#Override
public String getItem(int position) {
return fullList.get(position);
}
public class AutoCompleteAdapter extends ArrayAdapter<AutoCompleteObject> implements Filterable {
private ArrayList<AutoCompleteObject> fullList;
private ArrayList<AutoCompleteObject> mOriginalValues;
private ArrayFilter mFilter;
public AutoCompleteAdapter(Context context, int resource, int textViewResourceId, ArrayList<AutoCompleteObject> fullList) {
super(context, resource, textViewResourceId, fullList);
this.fullList = fullList;
mOriginalValues = new ArrayList<AutoCompleteObject>(fullList);
}
#Override
public int getCount() {
return fullList.size();
}
#Override
public String getItem(int position) {
return fullList.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return super.getView(position, convertView, parent);
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
private Object lock;
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (lock) {
mOriginalValues = new ArrayList<AutoCompleteObject>(fullList);
}
}
if (prefix == null || prefix.length() == 0) {
synchronized (lock) {
ArrayList<AutoCompleteObject> list = new ArrayList<AutoCompleteObject>(
mOriginalValues);
results.values = list;
results.count = list.size();
}
} else {
final String prefixString = prefix.toString().toLowerCase();
ArrayList<AutoCompleteObject> values = mOriginalValues;
int count = values.size();
ArrayList<AutoCompleteObject> newValues = new ArrayList<AutoCompleteObject>(count);
for (int i = 0; i < count; i++) {
String item = values.get(i);
if (item.toLowerCase().contains(prefixString)) {
newValues.add(item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
Filter.FilterResults results) {
if (results.values != null) {
fullList = (ArrayList<AutoCompleteObject>) results.values;
} else {
fullList = new ArrayList<AutoCompleteObject>();
}
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
How about this approach?
#Override
public String getItem(int position) {
AutoCompleteObject obj = fullList.get(position);
String item = obj.getYourValue() + " " + obj.getAnotherValue();
return item;
}
Of course, it means that you need to change generic type to String.
your getItem is returning a String, but fullList contains AutoCompleteObject. You should change it like
#Override
public AutoCompleteObject getItem(int position) {
return fullList.get(position);
}
your Adapter has generic type AutoCompleteObject (ArrayAdapter<AutoCompleteObject>). Also the super.getItem returns T, so you can't really change the signature of the method to make it return a String. If you do so you will get another compile time error

Search in listview via searchview

I have some troubles with my search in listview. I create my custom array adapter with Filter. If the result is correct then it always shows only the first item. When I use base array adapter the result is shown as correct but I need to use the custom adapter. Can you help me? This is my code of the array adapter:
public class ImageAdapter extends ArrayAdapter{
Activity context;
ArrayList<String> original;
ArrayList<String> fitems;
int layoutId;
int textId;
int imageId;
private Filter filter;
ImageAdapter(Activity context, int layoutId, int textId, int imageId, ArrayList<String> data){
super(context,layoutId,data);
this.context = context;
this.original = new ArrayList<>(data);
this.fitems = new ArrayList<>();
this.layoutId = layoutId;
this.textId = textId;
this.imageId = imageId;
}
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
public Object getItem(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent){
LayoutInflater inflater=context.getLayoutInflater();
View row=inflater.inflate(layoutId, null);
TextView label=(TextView)row.findViewById(textId);
label.setText(original.get(position));
ImageView icon=(ImageView)row.findViewById(imageId);
icon.setImageResource(R.drawable.arrow);
return(row);
}
#Override
public Filter getFilter(){
if (filter == null)
filter = new ListFilter();
return filter;
}
private class ListFilter extends Filter{
#Override
protected FilterResults performFiltering(CharSequence constraint){
FilterResults results = new FilterResults();
String prefix = constraint.toString().toLowerCase();
if (prefix == null || prefix.length() == 0){
ArrayList<String> list=new ArrayList<String>(original);
results.values = list;
results.count = list.size();
}
else{
ArrayList<String> values = new ArrayList<String>(original);
ArrayList<String> nlist = new ArrayList<String>();
final int count = values.size();
for (int i=0; i<count; i++){
final String value = values.get(i);
final String valueText = values.get(i).toLowerCase();
if (valueText.startsWith(prefix)){
nlist.add(valueText);
}
else{
final String[] words = valueText.split(" ");
final int wordCount = words.length;
// Start at index 0, in case valueText starts with space(s)
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefix)) {
nlist.add(value);
break;
}
}
}
}
results.values = nlist;
results.count = nlist.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
fitems = (ArrayList<String>)results.values;
notifyDataSetChanged();
clear();
for (int i=0; i<fitems.size(); i++){
String str = fitems.get(i);
add(str);
}
notifyDataSetInvalidated();
}
}
}
And I use it:
SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
public boolean onQueryTextChange(String newText) {
if (TextUtils.isEmpty(newText)) {
if(EventForList.size()!=0) {
imAdapter2.getFilter().filter("");
}
else
Toast.makeText(MainActivity.this,"List is empty",Toast.LENGTH_SHORT).show();
}
else {
if(EventForList.size()!=0) {
imAdapter2.getFilter().filter(newText);
}
else
Toast.makeText(MainActivity.this,"List is empty",Toast.LENGTH_SHORT).show();
}

AutoCompleteTextView always display complete list instead of filtering

I want to filter the text in autocompletetextview. When i start to enter the text the instead of display filtered text it display the complete list of text. I mean it does not filter the list.
Please help me to solve the issue. I tried but could not recognize the problem
public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> mData;
public AutoCompleteAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
mData = new ArrayList<String>();
mData.add("one");
mData.add("oneee");
mData.add("two");
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int index) {
return mData.get(index);
}
#Override
public Filter getFilter() {
Filter myFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<String> resultsSuggestions = new ArrayList<String>();
if(constraint != null) {
for (int i = 0; i < getCount(); i++) {
if(getItem(i).toString().startsWith(constraint.toString())){
resultsSuggestions.add(getItem(i).toString());
}
}
}
FilterResults results = new FilterResults();
results.values = resultsSuggestions;
results.count = resultsSuggestions.size();
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence contraint, FilterResults results) {
try {
ArrayList<String> newValues = (ArrayList<String>) results.values;
for (int i = 0; i < newValues.size(); i++) {
add(newValues.get(i));
}
if(results != null && results.count > 0) {
notifyDataSetChanged();
}
else {
notifyDataSetInvalidated();
}
} catch(Exception e) {
Log.v("Near ATM", "Exception ::" + e.getMessage());
}
}
};
return myFilter;
}
}
I would say your problem is in publishResults method. You should call notifyDataSetChanged() even if result.count == 0. And your getItem and getCount methods should work with filtered list. So your code should look like this:
public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> fullList;
private ArrayList<String> filtredList;
public AutoCompleteAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
filtredList = new ArrayList<String>();
fullList = new ArrayList<String>();
fullList.add("one");
fullList.add("oneee");
fullList.add("two");
}
#Override
public int getCount() {
return filtredList.size();
}
#Override
public String getItem(int index) {
return filtredList.get(index);
}
#Override
public Filter getFilter() {
Filter myFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<String> resultsSuggestions = new ArrayList<String>();
if(constraint != null) {
for (int i = 0; i < fullList.size(); i++) {
if(fullList.get(i).startsWith(constraint.toString())){
resultsSuggestions.add(fullList.get(i));
}
}
}
FilterResults results = new FilterResults();
results.values = resultsSuggestions;
results.count = resultsSuggestions.size();
filtredList = resultsSuggestions;
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence contraint, FilterResults results) {
try {
ArrayList<String> newValues = (ArrayList<String>) results.values;
for (int i = 0; i < newValues.size(); i++) {
add(newValues.get(i));
}
if(results != null) {
notifyDataSetChanged();
}
else {
notifyDataSetInvalidated();
}
} catch(Exception e) {
Log.v("Near ATM", "Exception ::" + e.getMessage());
}
}
};
return myFilter;
}
}

No results with custom ArrayAdapter Filter

I'm using the ArrayAdapter on a AutoCompleteTextView. results.values has the expected value but I get no list on the UI.
public class CustomArrayAdapter extends ArrayAdapter<String> implements Filterable {
private final Object mLock = new Object();
private CustomFilter mFilter;
public ArrayList<String> mItems;
public ArrayList<String> mFiltered;
public CustomArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
mItems = new ArrayList<String>();
mFiltered = new ArrayList<String>();
}
public Filter getFilter() {
if (mFilter == null) {
mFilter = new CustomFilter();
}
return mFilter;
}
#Override
public void add(String s) {
mItems.add(s);
}
private class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (mItems == null) {
synchronized (mLock) {
mItems = new ArrayList<String>();
}
}
if (constraint == null || constraint.length() == 0) {
synchronized (mLock) {
results.values = mItems;
results.count = mItems.size();
}
} else {
final ArrayList<String> newItems = new ArrayList<String>();
for (int i = 0; i < mItems.size(); i++) {
final String item = mItems.get(i);
if(item.contains(constraint)) {
newItems.add(item);
}
}
results.values = newItems;
results.count = newItems.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
mFiltered.clear();
mFiltered.addAll((ArrayList<String>) results.values);
notifyDataSetChanged();
}
}
}
Looks like overriding a couple more functions did the job.
Full source of working version:
public class CustomArrayAdapter extends ArrayAdapter<String> implements Filterable {
private List<String> mOrigionalValues;
private List<String> mObjects;
private Filter mFilter;
public CustomArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
mOrigionalValues = new ArrayList<String>();
mObjects = new ArrayList<String>();
}
public void add(String object) {
mOrigionalValues.add(object);
this.notifyDataSetChanged();
}
#Override
public int getCount() {
return mObjects.size();
}
#Override
public String getItem(int position) {
return mObjects.get(position);
}
public Filter getFilter() {
if (mFilter == null) {
mFilter = new CustomFilter();
}
return mFilter;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
private class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint == null || constraint.length() == 0) {
ArrayList<String> list = new ArrayList<String>(mOrigionalValues);
results.values = list;
results.count = list.size();
} else {
ArrayList<String> newValues = new ArrayList<String>();
for(int i = 0; i < mOrigionalValues.size(); i++) {
String item = mOrigionalValues.get(i);
if(item.contains(constraint)) {
newValues.add(item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
mObjects = (List<String>) results.values;
Log.d("CustomArrayAdapter", String.valueOf(results.values));
Log.d("CustomArrayAdapter", String.valueOf(results.count));
notifyDataSetChanged();
}
}
}
You need overwrite getCount method in CustomArrayAdapter:
#Override
public int getCount() {
return mFiltered.size();
}
And modify your publishResults method code:
protected void publishResults(CharSequence constraint,FilterResults results) {
mFiltered = (List<String>) results.values;
notifyDataSetChanged();
}
There are some days I have been researching on the net about how to do research in arraylist with hashmap and luckily I came across this post.
I made my adaptation to arraylist > and it worked. And now I'm sharing with you, you will know there is someone like the same question using ArrayList and HashMap. Thank you Pim Reijersen!
public class CategoriaAdapterModel extends BaseAdapter implements Filterable {
private Activity context;
private ArrayList<HashMap<String, String>> mDataShown;
private ArrayList<HashMap<String, String>> mAllData;
private Filter mFilter;
private LayoutInflater inflater;
DownloadImagemUtil downloader;
public CategoriaAdapterModel(Activity context,
ArrayList<HashMap<String, String>> data) {
this.context = context;
this.mAllData = data;
this.mDataShown = data;
downloader = new DownloadImagemUtil(context);
}
public void add(HashMap<String, String> object) {
mAllData.add(object);
this.notifyDataSetChanged();
}
public int getCount() {
return mDataShown.size();
}
public Object getItem(int position) {
return mDataShown.get(position);
}
public long getItemId(int position) {
return position;
}
public Filter getFilter() {
if (mFilter == null) {
mFilter = new CustomFilter();
}
return mFilter;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
private class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(
mAllData);
results.values = list;
results.count = list.size();
} else {
ArrayList<HashMap<String, String>> newValues = new ArrayList<HashMap<String, String>>();
for (int i = 0; i < mAllData.size(); i++) {
HashMap<String, String> item = mAllData.get(i);
if (item.get(JsonFragmentCategoriaCONN.TAG_NOME)
.toLowerCase()
.contains(constraint.toString().toLowerCase())) {
newValues.add(item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
mDataShown = (ArrayList<HashMap<String, String>>) results.values;
Log.d("CustomArrayAdapter", String.valueOf(results.values));
Log.d("CustomArrayAdapter", String.valueOf(results.count));
notifyDataSetChanged();
}
}

Categories

Resources