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();
}
}
}
}
Related
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 :)
Hey guys I've implemented my own ArrayAdapter because I have two textviews in the single ListView item.
While the filtering works fine(it shows the correct items), when I delete the text that I have typed to filter the items the ListView doesn't go to its initial state(it doesn't display all items), instead it just leaves the filtered list unchanged.
Here is my filter implementation:
private class NightFilter extends Filter {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
items = (ArrayList<NightOut>) results.values;
clear();
int count = items.size();
for (int i = 0; i < count; i++) {
NightOut pkmn = (NightOut) items.get(i);
add(pkmn);
}
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults result = new FilterResults();
if (constraint == null || constraint.length() == 0) {
ArrayList<NightOut> list = new ArrayList<NightOut>(nightsOut);
result.values = list;
result.count = list.size();
} else {
final ArrayList<NightOut> list = new ArrayList<NightOut>(nightsOut);
final ArrayList<NightOut> nlist = new ArrayList<NightOut>();
int count = list.size();
for (int i = 0; i < count; i++) {
final NightOut nightOut = list.get(i);
final String value = nightOut.getAddress().toLowerCase();
if (value.contains(constraint.toString().toLowerCase())) {
nlist.add(nightOut);
}
}
result.values = nlist;
result.count = nlist.size();
}
return result;
}
}
Both nightsOut and items contain the objects that i want to filter through(I assign those in the constructor). My custom adapter class extends ArrayAdapter if that's of any help.
Edit:
Added code for constructor and text filtering
public CustomArrayAdapter(Activity context, ArrayList<NightOut> nightsOut) {
super(context, R.layout.list_item, nightsOut);
this.context = context;
this.nightsOut = nightsOut;
this.items = nightsOut;
}
Search method
inputSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
ViewPlacesActivity.this.adapter.getFilter().filter(cs);
}
Any idea what I'm missing?
Cheers Kyle
The way you are using nightsOut as the source list for your ArrayAdapter and also the source list for the filter is what is causing the problem.
In the publishResults() method you have a call to clear() which removes all elements from the nightsOut list inside ArrayAdapter since that is the list it references. You then readd only the filtered data.
Then the next time call performFiltering() you are using nightsOut as the source list again which only includes the filtered items.
What you want to do instead is keep a reference to your original items. You don't really need items the way it is currently used so I would rename that to originalItems and do the following:
public CustomArrayAdapter(Activity context, ArrayList<NightOut> nightsOut) {
super(context, R.layout.list_item, nightsOut);
this.context = context;
this.nightsOut = nightsOut;
originalItems = new ArrayList<>(nightsOut); // create a copy of nightsOut.
}
And then the filter
private class NightFilter extends Filter {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
ArrayList<NightOut> tempList = (ArrayList<NightOut>) results.values;
clear();
addAll(tempList);
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults result = new FilterResults();
if (constraint == null || constraint.length() == 0) {
result.values = originalItems;
result.count = originalItems.size();
} else {
final ArrayList<NightOut> nlist = new ArrayList<NightOut>();
String lowerConstraint = constraint.toString().toLowerCase();
// loop through originalItems which always contains all items
for(NightOut nightOut : originalItems) {
final String value = nightOut.getAddress().toLowerCase();
if (value.contains(lowerConstraint)) {
nlist.add(nightOut);
}
}
result.values = nlist;
result.count = nlist.size();
}
return result;
}
}
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();
}
Here is the code, I used a custom adapter, and applied the Filter method, now the ListView does not update when the backspace key is entered, on when one switches back from an item activity. please help me.. and how to display no result to filtered list..
public class ItemListAdapter extends ArrayAdapter<ItemVO>
{
private ArrayList<ItemVO> itemList;
private ArrayList<ItemVO> fiems;
private static final int LONG_DELAY = 3500; // 3.5 seconds
private static final int SHORT_DELAY = 2000; // 2 seconds
private Context context;
private Filter filter;
public ItemListAdapter(Context context, int textViewResourceId,ArrayList<ItemVO> stateList)
{
super(context, textViewResourceId, stateList);
this.context = context;
this.itemList = new ArrayList<ItemVO>();
this.itemList.addAll(stateList);
this.fiems=new ArrayList<ItemVO>();
this.fiems.addAll(stateList);
}
private class ViewHolder
{
TextView code;
CheckBox name;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
Log.v("ConvertView", String.valueOf(position));
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.listview_items, null);
holder = new ViewHolder();
holder.code = (TextView) convertView.findViewById(R.id.textView1);
holder.name = (CheckBox) convertView.findViewById(R.id.checkBox1);
convertView.setTag(holder);
holder.name.setOnClickListener( new View.OnClickListener()
{
public void onClick(View v)
{
CheckBox cb = (CheckBox) v;
ItemVO item = (ItemVO) cb.getTag();
item.setSelected(cb.isChecked());
}
});
}
else
{
holder = (ViewHolder) convertView.getTag();
}
ItemVO state = itemList.get(position);
holder.code.setText(state.getItemdescription());
holder.name.setChecked(state.isSelected());
holder.name.setTag(state);
return convertView;
}
#Override
public Filter getFilter()
{
if (filter == null)
filter = new PkmnNameFilter();
return filter;
}
private class PkmnNameFilter extends Filter
{
#SuppressWarnings("unused")
#SuppressLint("DefaultLocale")
#Override
protected FilterResults performFiltering(CharSequence constraint)
{
FilterResults results = new FilterResults(); // Holds the results of a filtering operation in values
String prefix = constraint.toString().toLowerCase();
if (prefix == null || prefix.length() == 0)
{
ArrayList<ItemVO> list = new ArrayList<ItemVO>(fiems);
results.values = list;
results.count = list.size();
}
else
{
final ArrayList<ItemVO> list = new ArrayList<ItemVO>(fiems);
final ArrayList<ItemVO> nlist = new ArrayList<ItemVO>();
int count = list.size();
for (int i=0; i<count; i++)
{
final ItemVO pkmn = list.get(i);
final String value = pkmn.getItemdescription().toLowerCase();
if (value.startsWith(prefix))
{
nlist.add(pkmn);
}
/*else
{
final Toast toast= Toast.makeText(context, "No Items Found", Toast.LENGTH_SHORT);
toast.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toast.cancel();
}
}, 1000);
}*/
}
// set the Filtered result to return
results.values = nlist;
results.count = nlist.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
itemList = (ArrayList<ItemVO>)results.values; // has the filtered values
clear();
int count = itemList.size();
for (int i=0; i<count; i++)
{
ItemVO pkmn = (ItemVO)itemList.get(i);
add(pkmn);
notifyDataSetChanged(); // notifies the data with new filtered values
}
}
}
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
boolean notifyChanged = true;
}
}
In main activity for editetxt..
dataAdapter = new ItemListAdapter(this,R.layout.listview_items, itemList);
lv.setAdapter(dataAdapter);
final EditText searchBox=(EditText) findViewById(R.id.filter_text);
//searchBox.addTextChangedListener(this);
lv.setTextFilterEnabled(true);
// Add Text Change Listener to EditText
searchBox.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// Call back the Adapter with current character to Filter
Log.d("Constants.TAG", "*** Search value changed: " + cs.toString());
CateringList.this.dataAdapter.getFilter().filter(cs);
dataAdapter.notifyDataSetChanged();
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { }
#Override
public void afterTextChanged(Editable arg0) {
//if(arg0.length()==0)
// {
// }
}
});
You just need a validation if the ArrayList have data put it in your getView() method
if (itemList == null || itemList.size() == 0){
//do your code here
holder.code.setText("No Result");
}
Brother change this line:
clear();
int count = itemList.size();
for (int i=0; i<count; i++)
{
ItemVO pkmn = (ItemVO)itemList.get(i);
add(pkmn);
notifyDataSetChanged();
}
To this:
itemList = (ArrayList<ItemVO>)results.values;
notifyDataSetChanged();
Try this one:
private ArrayList<ItemVO> mItemList;
public Filter getFilter()
{
return new Filter(){
#Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oResults = new FilterResults();
final ArrayList<ItemVO> result = new ArrayList<ItemVO>();
If (mItemList == null)
mItemList = itemList;
if (constraint != null){
if (mItemList != null && mItemList.size > 0){
//loop
for (final ItemVO item : mItemList){
final String value = item.getItemdescription().toLowerCase();
if (value.startsWith(constraint.toString())){
result.add(item);
}
}
}
}
}
oResults.values = result;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,FilterResults results) {
itemList = (ArrayList<ItemVO>)results.values;
notifyDataSetChanged();
}
}
this is happening because listItems of your adapter are removed, but when you press backspace, they are not added back. For example,you have total 10 items in recyclerview, when you press 'A' you get 4 filtered items. Here 6 items removed from your actual listItems( which had 10 items before). But these removed items never added back.
Solution:
Check backpress and before filtering, make temp copy of you fullList First. And call filtering.
I am not sure if i can help you. Try to change this:
CateringList.this.dataAdapter.getFilter().filter(cs);
dataAdapter.notifyDataSetChanged();
You access dataAdapter in two different ways, and also i think you don't need to call here notifyDataSetChanged, so put instead:
dataAdapter.getFilter().filter(cs);
Also, if you want to display list with no results rty:
dataAdapter.getFilter().filter("");
EDIT :
Add this code to listen for edit text changes:
private TextWatcher filterTextWatcher = 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) {
Log.d("Constants.TAG", "*** Search value changed: " + cs.toString());
dataAdapter.getFilter().filter(cs);
};
And after initializing EditText put:
searchBox.addTextChangedListener(filterTextWatcher);
EDIT 2:
Change this:
if (prefix == null || prefix.length() == 0)
{
//ArrayList<ItemVO> list = new ArrayList<ItemVO>(fiems);
results.values = null;
results.count = 0;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
itemList = (ArrayList<ItemVO>)results.values; // has the filtered values
if(itemList != null) {
clear();
int count = itemList.size();
for (int i=0; i<count; i++)
{
ItemVO pkmn = (ItemVO)itemList.get(i);
add(pkmn);
}
notifyDataSetChanged(); // notifies the data with new filtered values
}
I've solved with this workaround... hope this one suit to you as well :)
searchBox.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// Call back the Adapter with current character to Filter
Log.d("Constants.TAG", "*** Search value changed: " + cs.toString());
CateringList.this.dataAdapter.getFilter().filter(cs);
dataAdapter.notifyDataSetChanged();
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
dataAdapter.itemList = OriginalItemList;
}
#Override
public void afterTextChanged(Editable arg0) {
//if(arg0.length()==0)
// {
// }
}
});
before the search search text was changed... just assign back the original data state to the adapter to filter again.
Every time you call onQueryTextChange, just refresh the data to your recyclerview
#Override
public boolean onQueryTextChange(String newText) {
rvAdapter = new RecyclerViewAdapter(Context, <list of files>);
recyclerView.setAdapter(rvAdapter);
rvAdapter.getFilter().filter(newText);
return true;
}
My question asked before : Link .If you do not understand me.
I have a listView with baseAdapter class on my app and my problem is:
User typing on the editText some letter in it and after the listView return him the all "Names" with this letter(addTextChangedListener) . now,
Evrything work fine but when the adapter set the "new list" with the result ,I Can't get the current Data from the current position from the list. Explain the theory :
my list is :
posistion 0. Name: A Phone: 111111
posistion 1. Name: B Phone: 222222
posistion 2. Name: C Phone: 333333
and when i type the letter "C" my list show this result:
position 0 : Name C: Phone: 111111 (phone is"111111" because that target to position "0")
but in "0" position i have the Phone value of A .
Here my code:
public class MainActivity extends Activity implements OnClickListener, OnItemClickListener {
ListView lv;
ArrayList<Person> contactList;
CustomContact adapterContact;
//Temp
ArrayList<String> groupList = new ArrayList<>();
ArrayList<String> groupListName = new ArrayList<>();
ArrayList<Person> tempList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
send = (Button) findViewById(R.id.bSend);
send.setOnClickListener(this);
txTempName = (TextView) findViewById(R.id.textTempName);
edNumber = (EditText)findViewById(R.id.edPhoneOrName);
edMass = (EditText)findViewById(R.id.edMass);
timepicker = (TimePicker)findViewById(R.id.timePickerMain);
timepicker.setIs24HourView(true);
datePicker = (DatePicker) findViewById(R.id.datePickerMain);
lv = (ListView) findViewById(R.id.listContact);
lv.setOnItemClickListener(this);
edNumber.addTextChangedListener(new TextWatcher() {
#SuppressWarnings("unchecked")
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.toString().trim().equalsIgnoreCase("")) {
refreshContact();
} else {
MainActivity.this.adapterContact.getFilter().filter(s);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
// // TODO Auto-generated method stub
}
});
}
public void refreshContact(){
DbHandContact hand = new DbHandContact(this);
hand.open();
contactList = hand.getAll();
hand.close();
Collections.sort(contactList,contactSort);
adapterContact = new CustomContact(this, contactList);
lv.setAdapter(adapterContact);
tempList = (ArrayList<Person>) contactList.clone();
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
if(true){
String currentCellPhone = tempList.get(position).getCellPhone();
String name = tempList.get(position).getName();
groupList.add(currentCellPhone);
groupListName.add(name);
Toast.makeText(this, currentCellPhone+" "+name, 2000).show();
for (int i = 0; i < groupList.size(); i++) {
txTempName.setText(groupList.get(i));
}
}
}
My Adapter class:
public class CustomContact extends BaseAdapter implements Filterable {
Activity context;
ArrayList<Person> list;
protected ArrayList<String> temporarylist;
public CustomContact(Activity context, ArrayList<Person> list) {
super();
this.context = context;
this.list = list;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
LayoutInflater inflater = context.getLayoutInflater();
row = inflater.inflate(R.layout.row_contact, parent,false);
ImageView imgPerson,ImgDial;
TextView txName,txLastName,txCellnum,HomeNum;
txName = (TextView) row.findViewById(R.id.row_name);
txLastName = (TextView) row.findViewById(R.id.row_lastName);
txCellnum = (TextView) row.findViewById(R.id.row_cellNum);
imgPerson = (ImageView) row.findViewById(R.id.row_picture);
txName.setText(list.get(position).getName());
txLastName.setText(list.get(position).getLastName());
txCellnum.setText(list.get(position).getCellPhone());
return row;
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
list = (ArrayList<Person>) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
ArrayList<Person> FilteredList = new ArrayList<Person>();
if (constraint == null || constraint.length() == 0) {
// No filter implemented we return all the list
results.values = list;
results.count = list.size();
} else {
for (int i = 0; i < list.size(); i++) {
String data = list.get(i).getName();
if (data.toLowerCase().contains(constraint.toString().toLowerCase())) {
FilteredList.add(list.get(i));
}
}
results.values = FilteredList;
results.count = FilteredList.size();
}
return results;
}
};
return filter;
}
}
Try this code Filter part code only change:
#Override public Filter getFilter() {
Filter filter = new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
list = (ArrayList<Person>) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
ArrayList<Person> FilteredList = new ArrayList<Person>();
if (constraint == null || constraint.length() == 0) {
// No filter implemented we return all the list
results.values = list;
results.count = list.size();
} else {
constraint = constraint.toString();
for (int i = 0; i < list.size(); i++) {
String data = list.get(i).getName();
if (data.toLowerCase().contains(constraint.toString())) {
FilteredList.add(list.get(i));
}
results.values = FilteredList;
results.count = FilteredList.size();
}
return results;
}
};
return filter;
}
and editext code here:
search.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// Call back the Adapter with current character to Filter
mAdapter.getFilter().filter(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
you can solve this issue by one of two cases that you can use application class and when it updated in adapter update it in the application class and then you can access from the activity/fragment and whenever you want
and the second option to use sharedpreferences to save it and the same for retrieving it at any place also