I have developed an activity that displays all the Contacts of Android phone and I am using a ListView to display the retrieved contacts. The problem is till the time I don't scroll my ListView, whenever I click on any list item - it is displaying that particular contact record details. But, when I scroll and click on any item in the list the application is crashing and throwing a NullPointerException. Can anyone guide me where am I going wrong and how to achieve my result. This may be a duplicate question, but I tried searching all over the net with no success. Below is the code snippet of my activity that displays contacts:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.contact_manager);
filterText = (EditText) findViewById(R.id.search_box);
filterText.addTextChangedListener(filterTextWatcher);
mContactList = (ListView) findViewById(R.id.contactList);
populateContactList();
}
private void populateContactList()
{
// Another class used to retrieve contacts
ContactAPI contactAPI = ContactAPI.getAPI();
ContentResolver cr = getContentResolver();
contactAPI.setCr(cr);
ArrayList<Contact> a = new ArrayList<Contact>();
a = contactAPI.newContactList(this).getContacts();
contactsAL = new ArrayList<Contact>(a);
adapter = new CustomAdapter(this, R.layout.contact_entry, a);
mContactList.setAdapter(adapter);
mContactList.setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
***// The below is the line where I am getting NullPointerException***
LinearLayout l = (LinearLayout) parent.getChildAt(position);
TextView tv = (TextView) l.getChildAt(1);
Intent myIntent = new Intent(view.getContext(), ContactDetailsActivity.class);
Bundle b = new Bundle();
b.putString("ContactID", tv.getText().toString());
myIntent.putExtras(b);
startActivityForResult(myIntent, 0);
}
});
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)
{
adapter.getFilter().filter(s);
}
};
protected void onDestroy()
{
super.onDestroy();
filterText.removeTextChangedListener(filterTextWatcher);
}
And below is my custom Adapter class code snippet:
private ArrayList<Contact> original;
private ArrayList<Contact> fitems;
private Filter filter;
private LayoutInflater mInflater;
public CustomAdapter(Context context, int layoutResourceId, ArrayList<Contact> data)
{
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.original = new ArrayList<Contact>(data);
this.fitems = new ArrayList<Contact>(data);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.contact_entry, null);
holder = new ViewHolder();
holder.txtName = (TextView) convertView.findViewById(R.id.contactEntryText);
holder.txtID = (TextView) convertView.findViewById(R.id.contactID);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
if(fitems != null)
{
Contact ct = fitems.get(position);
if(ct != null)
{
holder.txtName.setText((String)ct.getDisplayName());
holder.txtID.setText((String)ct.getId());
}
}
//this.notifyDataSetChanged();
return convertView;
}
#Override
public Filter getFilter() {
// TODO Auto-generated method stub
// return super.getFilter();
if (filter == null)
filter = new ContactFilter();
return filter;
}
private class ContactFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence constraint)
{
FilterResults results = new FilterResults();
String prefix = constraint.toString().toLowerCase();
if (prefix == null || prefix.length() == 0)
{
ArrayList<Contact> list = new ArrayList<Contact>(original);
results.values = list;
results.count = list.size();
}
else
{
final ArrayList<Contact> list = new ArrayList<Contact>(original);
final ArrayList<Contact> nlist = new ArrayList<Contact>();
int count = list.size();
for (int i=0; i<count; i++)
{
final Contact cont = list.get(i);
final String value = cont.getDisplayName().toLowerCase();
if (value.contains(prefix))
{
nlist.add(cont);
}
}
results.values = nlist;
results.count = nlist.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
fitems = (ArrayList<Contact>)results.values;
clear();
int count = fitems.size();
for (int i=0; i<count; i++)
{
Contact cont = (Contact)fitems.get(i);
add(cont);
}
}
}
static class ViewHolder {
TextView txtName;
TextView txtID;
}
Can anyone please suggest me where am I doing wrong?
int the onItemClick call CustomAdapter.getItem(int) to retrive the Contact object at position, a use contact to retrive the information you need to start the new activity.
remove setting onitemclicklistener in your main activity.
In CustomAdapter, inside getView method you just add clicklistener to textview
holder.txtName.setOnclickListener(new OnClickListener() {
#Override
public void onClick() {
Intent myIntent = new Intent(view.getContext(), ContactDetailsActivity.class);
Bundle b = new Bundle();
b.putString("ContactID", holder.txtName.getText().toString());
myIntent.putExtras(b);
startActivityForResult(myIntent, 0);
}
})
Related
I'm trying to implement a search function in my application. I have used an adapter to because I want to display 2 textviews in listview and listview should be clickable (I don;t think it's possible to do without an adapter).
My problem is I can't use addTextChangedListener in the adapter class. it gives exception (It worked in my activity class).
search activity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_results_activity);
new SearchMenuAsyncTask(getApplicationContext(), this).execute();
listtv = (LinearLayout) findViewById(R.id.product_lv);
lv = (ListView) findViewById(R.id.list_view);
inputSearch = (EditText) findViewById(R.id.inputSearch);
inputSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
System.out.println("Text ["+s+"]");
adapter.getFilter().filter(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
#Override
public void onTaskCompleted(JSONArray responseJson) {
try {
final List<String> descriptions = new ArrayList<String>();
final List<String> menudescriptions = new ArrayList<String>();
for (int i = 0; i < responseJson.length(); ++i) {
final JSONObject object = responseJson.getJSONObject(i);
if ((object.getString("MainCategoryID")).equals("5")
&& (object.getString("SubCategoryID")).equals("6")
&& (object.getString("Visible")).equals("true")) {
Log.i("descriptionsBev ", object.getString("Description"));
descriptions.add(object.getString("Description"));
Log.i("MenuDescription ",
object.getString("MenuDescription"));
menudescriptions
.add(object.getString("MenuDescription"));
}
adapter = new CustomListSearch(
getApplicationContext(), descriptions,
menudescriptions);
lv.setAdapter(adapter);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
CustomListSearch.java
public class CustomListSearch extends BaseAdapter implements Filterable {
private Context context;
private final List<String> descriptions;
private List<String>filteredData = null;
private final List<String> menudescriptions;
private ItemFilter mFilter = new ItemFilter();
private LayoutInflater mInflater;
ArrayAdapter<String> adapter;
public CustomListSearch(Context c, List<String> data,
List<String> menudescriptions) {
this.context = c;
this.filteredData = data ;
this.descriptions = data;
this.menudescriptions = menudescriptions;
mInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return filteredData.size();
}
#Override
public Object getItem(int position) {
return filteredData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
private TextView tvMenudescriptions;
private TextView tvDescriptions;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(
R.layout.search_list_item, parent, false);
holder.tvDescriptions = (TextView) convertView
.findViewById(R.id.product_name);
holder.tvMenudescriptions = (TextView) convertView
.findViewById(R.id.product_description);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvDescriptions.setText(descriptions.get(position));
holder.tvMenudescriptions.setText(menudescriptions.get(position));
LinearLayout itemlist = (LinearLayout) convertView
.findViewById(R.id.product_lv);
itemlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "Still under constructions...",
Toast.LENGTH_LONG).show();
}
});
return convertView;
}
#Override
public Filter getFilter() {
// TODO Auto-generated method stub
return mFilter;
}
private class ItemFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
final List<String> list = descriptions;
int count = list.size();
final ArrayList<String> nlist = new ArrayList<String>(count);
String filterableString ;
for (int i = 0; i < count; i++) {
filterableString = list.get(i);
if (filterableString.toLowerCase().contains(filterString)) {
nlist.add(filterableString);
}
}
results.values = nlist;
results.count = nlist.size();
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredData = (ArrayList<String>) results.values;
notifyDataSetChanged();
}
}
}
I was following below answer and worked this out
Custom Listview Adapter with filter Android
I am using a custom adapter with a search filter in a fragment, however the results don't get filtered on a search, I debugged and stepped through my code and find that it is saying that the args.listenere = null!. What does this mean and how do I correct it? My code is below:
---------Custom Adapter -------
public class SalesPartAdapter extends BaseAdapter implements Filterable {
private ArrayList<SalesPartItem> listData;
private ArrayList<SalesPartItem> filteredData;
private SalesPartFilter filter;
private Context _context;
private LayoutInflater layoutInflater;
public SalesPartAdapter(Context context, ArrayList<SalesPartItem> listData) {
this.listData = listData;
layoutInflater = LayoutInflater.from(context);
_context = context;
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
//set background colour
if (convertView == null) {
//set up holder
convertView = layoutInflater.inflate(R.layout.salespart_item, null);
holder = new ViewHolder();
holder.salesPartCodeView = (TextView) convertView.findViewById(R.id.salesPartCode);
holder.salesPartDescView = (TextView) convertView.findViewById(R.id.salesPartDescription);
holder.salesPartColourBar= (ImageView) convertView.findViewById(R.id.colourBar);
convertView.setTag(holder);
} else {
//use existing holder
holder = (ViewHolder) convertView.getTag();
}
SalesPartItem salespartView = (SalesPartItem) listData.get(position);
holder.salesPartCodeView.setText(salespartView.SalesPartCode);
holder.salesPartDescView.setText(salespartView.SalesPartDescription);
holder.salesPartColourBar.setBackgroundColor(Color.parseColor(salespartView.Colour));//String.valueOf(salespartView.Colour);
return convertView;
}
/********* holder Class to contain previously inflated xml file elements *********/
static class ViewHolder {
TextView salesPartCodeView;
TextView salesPartDescView;
ImageView salesPartColourBar;
}
public Filter getFilter() {
if (filter == null){
filter = new SalesPartFilter();
}
return filter;
}
ArrayList<SalesPartItem> filteredItems;
ArrayList<Integer>countFilteredItems;
private class SalesPartFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString().toLowerCase();
FilterResults result = new FilterResults();
if(constraint != null && constraint.toString().length() > 0)
{
filteredItems = new ArrayList<SalesPartItem>();
// countFilteredItems = new ArrayList<Integer>();
for(int i = 0, l = listData.size(); i < l; i++)
{
SalesPartItem salesPartItem = listData.get(i);
if(salesPartItem.SalesPartDescription.toString().toLowerCase().contains(constraint))
filteredItems.add(salesPartItem);
// countFilteredItems.add(i);
}
result.count = filteredItems.size();
result.values = filteredItems;
}
else
{
synchronized(this)
{
result.values = listData;
result.count = listData.size();
}
}
return result;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// notifyDataSetChanged();
if (results.count > 0) {
listData =(ArrayList<SalesPartItem>)results.values;
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
----------------Fragment code that deals with the list view -------------------
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//USE SAMPLE ID TO GET SALES PARTS LIST FROM DATABASE
addSalesParts.setEnabled(false);
//ListViewModel (SalesPartId,salesPartName,NotUsed)
final int numberOfAddedSalesParts = 3;
SalesPartItem sp;
// fill with some dummy data for now.
for (long i = 1; i < numberOfAddedSalesParts; i++) {
sp = new SalesPartItem();
sp.SalesPartItemId = i;
sp.SalesPartCode = "LEU" + i;
if(i!=2){
sp.SalesPartDescription = "Sales Part " + i;
}
else{
sp.SalesPartDescription = "TSalZes Part " + i;
}
sp.Colour = "#cccccc";
salesPartListViewItems.add(sp);
}
// Start of Search filtering
mListView = (ListView) getActivity().findViewById(R.id.salespartsList);
//click on item - edit order
mListView.setTextFilterEnabled(true);
//display the list via our custom adapter
mListView.setAdapter(new SalesPartAdapter(getActivity(), salesPartListViewItems);
EditText searchField = (EditText) getActivity().findViewById(R.id.typeFindSalesPart);
searchField.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
//TODO Search Lists from Database and filter accordingly
SalesPartAdapter SA = new SalesPartAdapter(getActivity(), salesPartListViewItems);
SA.getFilter().filter(s.toString());
Toast.makeText(getActivity(), s, Toast.LENGTH_SHORT).show();
// salesPartListViewItems.contains(s);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
I have now resolved this, the issue was that I was creating a new instance of the adapter in the text watcher. Once I set it to use the adapter that created the original list then it worked fine
I have a Listview in my asynctask and i am setting the adapter. I should implement the autosearch complete feature. My codes works fine but the list is not filtered when i enter the text in editable textview.
#Override
protected void onPostExecute(ArrayList<RouteTrackerUser> result)
{
dialog.dismiss();
if(result!=null)
{
//System.out.println("User with result===>"+result);
/*for(RouteTrackerUser r :result ){
System.out.println("Contents===>"+r.getStoreid()+" "+r.getStorename()+" "+r.getStorecode()+" "+r.getStoreno()+" "+r.getVisitcount());}
*/ Intent intent=getIntent();
TextView username=(TextView)findViewById(R.id.usrname);
final String sname=intent.getExtras().getString("user_name");
username.setText("Welcome, "+sname);
userList = (ListView) findViewById(R.id.historylist);
userAdapter = new HistoryAdapter(History.this, R.layout.history_visits,R.id.vcount,result);
userList.setAdapter(userAdapter);
EditText inputSearch = (EditText) findViewById(R.id.autocomplete);
inputSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
System.out.println("afafasdf"+cs);
History.this.userAdapter.getFilter().filter(cs);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
and my customAdapter is as follows :
private static class ViewHolder {
public final TextView storename;
public final TextView storevisitcount;
public ViewHolder(TextView name, TextView count) {
this.storename = name;
this.storevisitcount = count;
}
}
public class HistoryAdapter extends ArrayAdapter<RouteTrackerUser>
{
Context context;
//EditText autocomplete;
public HistoryAdapter(Context context,int resource,int textViewResourceId,ArrayList<RouteTrackerUser> result) {
super(context,resource,textViewResourceId, result);
this.context=context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView name;
TextView vcount;
final RouteTrackerUser User = getItem(position);
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.history_visits, parent, false);
name = (TextView) convertView.findViewById(R.id.sname);
vcount = (TextView) convertView.findViewById(R.id.vcount);
convertView.setTag(new ViewHolder(name, vcount));
convertView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
viewdata(User.getUsername(),User.getUid(),User.getStoreid(),User.getStorename(),User.getStorecode(),User.getStoreno(),User.getVisitcount());
}});
} else {
ViewHolder viewHolder = (ViewHolder) convertView.getTag();
name = viewHolder.storename;
vcount = viewHolder.storevisitcount;
}
name.setText(User.getStorename());
vcount.setText("Visit Count: "+User.getVisitcount());
return convertView;
}
}
Note: My main class name is History.java and Asynctask name is HistorySoapTask.
After searching few blogs and other posts i found the answer for my question. I made a mistake, i doesn't implement the Filter concept in my program and now it works fine. So to filter the list we should define the filter as below :
private class OrderAdapterFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString().toLowerCase();
FilterText = (String) constraint;
FilterResults result = new FilterResults();
if(constraint != null && constraint.toString().length() > 0)
{
ArrayList<RouteTrackerUser> filt = new ArrayList<RouteTrackerUser>();
ArrayList<RouteTrackerUser> lItems = new ArrayList<RouteTrackerUser>(fullitems);
for(int i = 0, l = lItems.size(); i < l; i++)
{
RouteTrackerUser m = lItems.get(i);
if(m.getStorename().toLowerCase().contains(constraint))
filt.add(m);
}
result.count = filt.size();
result.values = filt;
}
else
{
ArrayList<RouteTrackerUser> list = new ArrayList<RouteTrackerUser>(fullitems);
result.values = list;
result.count = list.size();
}
return result;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// NOTE: this function is *always* called from the UI thread.
filtered = (ArrayList<RouteTrackerUser>)results.values;
originalitems.clear();
for(int i = 0, l = filtered.size(); i < l; i++)
originalitems.add(filtered.get(i));
notifyDataSetChanged();
}
}
So I have a basic custom listview with an image and text for each list item and I was wondering how I would filter through the listview dynamically with an edittext box. I looked up how to do it but I'm stuck at one point where I'm not sure what to do.
My listview is populated from an sqlitedatabase where I have methods that retrieve all the images names, text and ids from the database and puts them into the listview. Here is my code so far where I'm not quite sure what I should be doing in the publishResult() method
public class MainActivity extends Activity {
ListView data;
EditText inputSearch;
ArrayList<String> names, images, ids;
ArrayAdapter<String> adapter;
MyDatabase helper;
ImageView sprite;
TextView name, id;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
data = (ListView) findViewById(R.id.listView1);
helper = new MyDatabase(this);
helper.openDataBase();
names = helper.getNameList();
images = helper.getImageList();
ids = helper.getIdList();
adapter = new MyArrayAdapter(this);
data.setAdapter(adapter);
inputSearch = (EditText) findViewById(R.id.edit_search);
inputSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
adapter.getFilter().filter(cs);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
private class MyArrayAdapter extends ArrayAdapter<String>{
public MyArrayAdapter(Context c) {
super(c, R.layout.item_view,names);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (convertView == null){
row = getLayoutInflater().inflate(R.layout.item_view, parent,false);
}
sprite = (ImageView) row.findViewById(R.id.sprite);
name = (TextView) row.findViewById(R.id.name);
id = (TextView) row.findViewById(R.id.ids);
name.setText(names.get(position).toString());
int resID = getResources().getIdentifier(images.get(position),"drawable", getPackageName());
sprite.setImageResource(resID);
id.setText(ids.get(position).toString());
return row;
}
#Override
public Filter getFilter() {
// TODO Auto-generated method stub
return new Filter(){
#Override
protected FilterResults performFiltering(CharSequence input) {
FilterResults results = new FilterResults();
int originalLength = names.size();
if (input == null || input.length() == 0){
results.values = names;
results.count = originalLength;
} else {
ArrayList<String> newList = new ArrayList<String>();
for (int i = 0; i < originalLength; i++){
String str = names.get(i);
if (str.toLowerCase(Locale.getDefault()).contains(input))
newList.add(str);
results.values = newList;
results.count = newList.size();
}
}
return results;
}
#Override
protected void publishResults(CharSequence charSequence,
FilterResults results) {
//Not sure what to do here
notifyDataSetChanged();
}
};
}
}
Try this , I think it help you.
#Override
protected void publishResults(CharSequence charSequence,
FilterResults results) {
if(results.count==0)
{
notifyDataSetInvalidated();
}else
{
names=(ArrayList<String> names)results.values;
notifyDataSetChanged();
}
}
Thanks
Should be pretty simple at that point...
Edit:
public class FakeAdapter extends ArrayAdapter<Model> {
public class Model {
String my_string;
int resource_id;
}
private Activity activity;
/* ArrayList to hold the original values before filtering. */
private ArrayList<Model> original_list;
/* Current Data Filter */
private Filter filter;
public RelationshipsAdapter(Activity activity, int resource,
ArrayList<Model> objects) {
super(activity, resource, objects);
this.activity = activity;
this.original_list = objects;
}
/**
* Viewholder pattern to minimize findViewById calls.
*/
private static class ViewHolder {
TextView name;
ImageView image;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Model currentmodel = getItem(position);
View rowView = null;
if(convertView == null){
rowView = activity.getLayoutInflater().inflate(R.layout.my_item, parent, false);
final ViewHolder holder = new ViewHolder();
holder.name = (TextView) rowView.findViewById(R.id.item_text);
holder.image = (ImageView) rowView.findViewById(R.id.item_image);
rowView.setTag(holder);
} else {
rowView = convertView;
}
ViewHolder holder = (ViewHolder) rowView.getTag();
holder.name.setText(currentmodel.my_string);
holder.friendship.setImageResource(currentmodel.resource_id);
return rowView;
};
/**
* Returns a filter to the calling activity to filter the underlying data set by name.
*/
#Override
public Filter getFilter(){
if(filter == null){
filter = new ModelFilter();
}
return filter;
}
/** Custom Filter implementation used to filter names alphabetically on a provided prefix. */
private class ModelFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence search) {
FilterResults filter_results = new FilterResults();
String prefix = search.toString();
/* If the search is empty, display the original dataset. */
if(UserInputValidation.checkText(prefix).equals(StatusCode.NULL_INPUT)){
filter_results.values = original_list;
filter_results.count = original_list.size();
} else {
//make a copy of the original items and use that array list
final ArrayList<RelationshipModel> results = new ArrayList<RelationshipModel>(original_list);
final ArrayList<RelationshipModel> results_holder = new ArrayList<RelationshipModel>();
int count = results.size();
for(int i = 0; i < count; i++){
final RelationshipModel model = results.get(i);
final String name = (model.first_name + " " + model.last_name).toLowerCase(Locale.US);
if(name.contains(prefix))
results_holder.add(model);
}
filter_results.values = results_holder;
filter_results.count = results_holder.size();
}
return filter_results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
clear();
addAll((ArrayList<RelationshipModel>) results.values);
}
}
}
I'm trying to implement an edit text on top of a list view to make searches on my list.
The search with Edit Text is not working very well, some customer names he can think and not others.
Please help me, below is the code
public class MainActivity extends Activity {
private List<Cliente> listaClientes = null;
public ClienteAdapter adapter;
private ArrayList<Cliente> arraycli = new ArrayList<Cliente>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lista = (ListView) findViewById(R.id.listView1);
arraycli.add(new Cliente("luis", R.drawable.ic_action_search));
arraycli.add(new Cliente("aaaaa", R.drawable.ic_launcher));
arraycli.add(new Cliente("bbbb", R.drawable.ic_launcher));
arraycli.add(new Cliente("ccccc", R.drawable.ic_launcher));
arraycli.add(new Cliente("aaaa", R.drawable.ic_launcher));
arraycli.add(new Cliente("testeeeeee", R.drawable.ic_launcher));
final ClienteAdapter adapter = new ClienteAdapter(this, R.id.listView1, arraycli);
lista.setAdapter(adapter);
EditText procurar = (EditText) findViewById(R.id.edprocurar);
procurar.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s.toString());
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
}
}
My Custom Adapter
ublic class ClienteAdapter extends ArrayAdapter<Cliente> {
public ArrayList<Cliente> original;
public ArrayList<Cliente> fitems;
private Filter filter;
public ClienteAdapter(Context context, int textViewResourceId,
ArrayList<Cliente> items) {
super(context, textViewResourceId, items);
this.original = new ArrayList<Cliente>(items);
this.fitems = new ArrayList<Cliente>(items);
}
private class ViewHolder {
public TextView ClienteNome;
public ImageView ClienteImg;
}
public void addItem(final Cliente item)
{
this.original.add(item);
}
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
ViewHolder holder;
if (v == null)
{
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.clienteitem, null);
holder = new ViewHolder();
holder.ClienteNome = (TextView) v.findViewById(R.id.clinome);
holder.ClienteImg = (ImageView) v.findViewById(R.id.imagem_plista);
v.setTag(holder);
}
else
holder = (ViewHolder)v.getTag();
final Cliente cliente = original.get(position);
if (cliente != null) {
holder.ClienteNome.setText(cliente.getNomeCliente());
holder.ClienteImg.setImageResource(cliente.getImagemCliente());
}
return v;
}
public Filter getFilter()
{
if (filter == null)
filter = new ClassClienteFiltro();
return filter;
}
private class ClassClienteFiltro extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
String prefix = constraint.toString().toLowerCase();
if (prefix == null || prefix.length() == 0)
{
ArrayList<Cliente> list = new ArrayList<Cliente>(original);
results.values = list;
results.count = list.size();
}
else
{
final ArrayList<Cliente> list = new ArrayList<Cliente>(original);
final ArrayList<Cliente> nlist = new ArrayList<Cliente>();
int count = list.size();
for (int i=0; i<count; i++)
{
final Cliente clienteclass = list.get(i);
final String value = clienteclass.getNomeCliente().toLowerCase();
if (value.startsWith(prefix))
{
nlist.add(clienteclass);
}
}
results.values = nlist;
results.count = nlist.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
fitems = (ArrayList<Cliente>)results.values;
clear();
int count = fitems.size();
for (int i=0; i<count; i++)
{
Cliente cliente = (Cliente)fitems.get(i);
add(cliente);
}
}
}
}
I saw many examples in the forum, but unfortunately could not make it work 100%. please help me.
Already thanks for listening
I do something similar in my app, but instead of using the Adapter to do the searching I do the searching logic within the onTextChanged Method.
This can be achieved by creating a secondary ArrayList based on what the user types, then creating a secondary Adapter with the updated information.
Whenever a user types do the folliwng:
A. Clear the Secondary ArrayList.
B. Go through the Primary ArrayList and search for names that match what the user types.
C. Add these items to your Secondary ArrayList.
D. Create a new Adapter with your Secondary ArrayList.
E. Set your ListView's adapter to the new one.
arraycliSort = new ArrayList<Cliente>(); //secondary ArrayList
yourEditText.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){
textlength = yourEditText.getText().length();
arraycliSort.clear(); //A
for (int i = 0; i < arraycli.size(); i++) { //B
if (textlength <= arraycli.get(i).name.length()) {
if (yourEditText.getText().toString().equalsIgnoreCase((String) arraycli.get(i).name.subSequence(0,textlength)))
{
arraycliSort.add(arraycli.get(i)); //C
}
}
}
adapter = new ClientAdapter(this, R.id.listView1, arraycli); //D
yourListView.setAdapter(adapter); //E
}
});
In my example I am not sure how you access the names you are searching for, so I used arraycli.get(i).name, you will have to adjust as necessary.
Hope this can help.