I have an autocomplete textview in my app that would let user enter address and the textview uses Places Api to show them different places that start with those letters the user is using. I implemented the Places Api and the user is able to see places but when they select a place I would like to retrieve that place and use it according to my needs(like retrieving the LatLng, and stuff like that) but the place object is String object and I don't know how to retrieve it as Place or convert the String object to Place object. I tried the following so far to no avail.
This is my adapter class.
class GooglePlacesAutocompleteAdapter extends ArrayAdapter implements Filterable {
private ArrayList resultList;
public GooglePlacesAutocompleteAdapter(Context context, int list, int textViewResourceId) {
super(context, list, textViewResourceId);
}
#Override
public int getCount() {
return resultList.size();
}
#Override
public String getItem(int index) {
return resultList.get(index).toString();
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
// Retrieve the autocomplete results.
resultList = autocomplete(constraint.toString());
// Assign the data to the FilterResults
filterResults.values = resultList;
filterResults.count = resultList.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return filter;
}
}
msg.setAdapter(new GooglePlacesAutocompleteAdapter(this, R.layout.search_results_list_item, R.id.tvSearchResultItem));
msg.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final String selectedPlace = (String) parent.getItemAtPosition(position);
Place pl = new Place() {
#Override
public String getId() {
return null;
}
#Override
public List<Integer> getPlaceTypes() {
return null;
}
#Override
public CharSequence getAddress() {
return null;
}
#Override
public Locale getLocale() {
return null;
}
#Override
public CharSequence getName() {
return selectedPlace;
}
#Override
public LatLng getLatLng() {
return null;
}
#Override
public LatLngBounds getViewport() {
return null;
}
#Override
public Uri getWebsiteUri() {
return null;
}
#Override
public CharSequence getPhoneNumber() {
return null;
}
#Override
public float getRating() {
return 0;
}
#Override
public int getPriceLevel() {
return 0;
}
#Override
public Place freeze() {
return null;
}
#Override
public boolean isDataValid() {
return true;
}
};
LatLng selectedltlng = getSelectedLatLng(pl);
Log.e("selected", selectedltlng.toString());
//Place selectedPlace = Places.GeoDataApi.getPlaceById(mGoogleApiClient, );
//Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
}
private LatLng getSelectedLatLng(Place placeStringe) {
LatLng placeltlg = placeStringe.getLatLng();
Log.e("selcete", placeltlg.toString());
return placeltlg;
}
});
But this throws a null pointer exception.
I also tried to cast the string object as Object like this
Object selectedPlace = (Object) parent.getItemAtPosition(position);
Place plac = (Place)selectedPlace;
But this throws cast exception. How can I do that in an efficient way?
I made a city selector a week ago. It use custom extended AutoCompleteTextView widget. May be this helps you. This widget allows user to enter chars (grey color) and then show list of matched cities. User select a city from the list (it became black) and then selected city saved in cityData object and could be retrived by .getCity() call.
Here is the code:
public class CityAutoCompleteEditText extends AutoCompleteTextView implements View.OnFocusChangeListener, TextWatcherAdapter.TextWatcherListener {
// City object (code, name, type, level and so on)
private OKTMOUnit cityData;
// One of the constructors. You need to implement all with init() inside
public CityAutoCompleteEditText(Context context) {
super(context);
init(context, null);
}
// Initial data setter
public void setCity(OKTMOUnit city) {
setText(city.toString());
setTextColor(resource_black);
cityData = city;
}
// Data getter
public OKTMOUnit getCity() {
return cityData;
}
private void init(Context context, AttributeSet attrs) {
......
super.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// On click - set color black and init cityData
cityData = (OKTMOUnit) getAdapter().getItem(position);
setTextColor(resource_black);
}
});
.....
}
#Override
public void onTextChanged(EditText view, String text) {
// Text changed by hand - grey it and clear cityData
cityData = null;
setTextColor(resource_grey);
}
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (cityData == null) {
setText("");
}
}
}
And adapter:
public class CityAutoCompleteAdapter extends BaseAdapter implements Filterable {
private static final int MAX_RESULTS = 20;
private Context mContext;
private ArrayList<OKTMOUnit> mData;
public CityAutoCompleteAdapter(Context context) {
mData = new ArrayList<>();
mContext = context;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public OKTMOUnit getItem(int index) {
return mData.get(index);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.autocomplete_dropdown_item, parent, false);
}
if (convertView != null) {
((TextView) convertView.findViewById(R.id.autoCompleteCity)).setText(getItem(position).getFullCity());
((TextView) convertView.findViewById(R.id.autoCompleteRegion)).setText(getItem(position).getFullRegion());
}
return convertView;
}
}
ADD: I removed public Filter getFilter() {} code from adapter to simplify it.
try this It is done with Model Class u can get place name,address,lat,long I found very useful http://coderzpassion.com/android-working-google-places-api/
Related
I have a custom ListView. It works fine except when attempting to filter a user search.
The code for displaying the ListView:
private void listShow() {
warranties=db.getAllServWarr();
adapter=new WarrantyAdapter(serviceswarranty_activity.this,warranties);
listView.setAdapter(adapter);
}
The code that implements the filter in the custom adapter:
public class WarrantyAdapter extends ArrayAdapter implements Filterable{
private ArrayList<ServicesWarranty> warrantyList;
private ArrayList<ServicesWarranty> filteredList;
private ItemFilter mFilter = new ItemFilter();
private Context context;
private int currPosition;
public WarrantyAdapter(#NonNull Context context,ArrayList<ServicesWarranty> warrantyList) {
super(context, R.layout.serviceswarranty_item,warrantyList);
this.warrantyList=warrantyList;
this.filteredList=warrantyList;
this.context=context;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
ServicesWarranty sw=warrantyList.get(position);
currPosition=position;
WarrantyAdapter.ViewHolder holder;
if(convertView==null){
LayoutInflater inflater=(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView=inflater.inflate(R.layout.serviceswarranty_item,parent,false);
holder=new WarrantyAdapter.ViewHolder();
holder.lockno=(TextView)convertView.findViewById(R.id.lockNum_warrantyitem);
holder.fromdate=(TextView)convertView.findViewById(R.id.fromDate_warrantyItem);
holder.todate=(TextView)convertView.findViewById(R.id.toDate_warrantyItem);
holder.editIc=(ImageView)convertView.findViewById(R.id.editic_warrantyItem);
holder.deleteIc=(ImageView)convertView.findViewById(R.id.deleteic_warrantyItem);
convertView.setTag(holder);
}else{
holder=(WarrantyAdapter.ViewHolder) convertView.getTag();
}
holder.fill(sw);
return convertView;
}
private class ViewHolder{
public TextView lockno;
public TextView fromdate;
public TextView todate;
public ImageView editIc;
public ImageView deleteIc;
public void fill(final ServicesWarranty sw){
lockno.setText(String.valueOf(sw.getLockNumber()));
fromdate.setText(sw.getBeginDate());
todate.setText(sw.getEndDate());
editIc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(context,Add2warranty.class);
intent.putExtra("AddedWarrantyLockNo",sw.getLockNumber().toString());
context.startActivity(intent);
}
});
deleteIc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AlertDialog.Builder deleteAlert=new AlertDialog.Builder(context);
deleteAlert.setMessage("آیا از حذف گارانتی با شماره قفل "+sw.getLockNumber().toString()+" اطمینان دارید؟")
.setPositiveButton("بله", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
AppDBHelper db=new AppDBHelper(context);
boolean res=db.deleteFromWarranty(sw.getID());
if(res) {
Toast.makeText(context, "Delete successfully", Toast.LENGTH_SHORT).show();
warrantyList.remove(currPosition);
notifyDataSetChanged();
}
}
})
.setNegativeButton("خیر",null)
.show();
}
});
}
}
public Filter getFilter() {
return mFilter;
}
private class ItemFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String filterString = constraint.toString();
FilterResults results = new FilterResults();
final List<ServicesWarranty> list = filteredList;
int count = list.size();
final ArrayList<ServicesWarranty> nlist = new ArrayList<ServicesWarranty>(count);
String filterableString ;
for (int i = 0; i < count; i++) {
filterableString = list.get(i).getLockNumber().toString();
if (filterableString.toLowerCase().contains(filterString)) {
nlist.add(list.get(i));
}
}
results.values = nlist;
results.count = nlist.size();
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
warrantyList = (ArrayList<ServicesWarranty>) results.values;
notifyDataSetChanged();
}
}
}
and also i add this to my activity to enable search by filter
inputSearch.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
if(s.length()>0)
adapter.getFilter().filter(s);
return false;
}
});
When I debug this program, the adapter.getFilter().filter(s); works correctly, but near the end of function the program force closes.
Here is my logcat info
FATAL EXCEPTION: main
Process: com.example.zahra.prj1, PID: 18592
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
In my ListView, I have 2 items with values 13 and 14. I type 4 in search text box so the list size should be one.
Why is the filtering not working? Thanks for any help.
The problem is the array is out of bounds because getCount() is returning the size of the warrantyList instead of the filteredList.
There is a good example of how to handle the two lists here:
Implementing Filterable
But in general, the WarrantyAdapter should be using the filteredList. The ItemFilter should be using the warrantyList to publish the filteredList.
I have your code running in my environment with the following changes:
#Override
public int getCount() {
return filteredList.size();
}
#Override
public Object getItem(int position) {
return filteredList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
and I modified WarrantyAdapter to extend BaseAdapter and inside getView I use the filteredList...
I have custom listview using simple adapter, Currently I have issue regarding filter that I have custom list data with numbers and characters in listview.
If I enter name then its give one blank space the filter results gets disappear.
I have list data like name then number for example : NAME 123, Whenever I enter name then gives space in that edit text then results are gone and list-view gets disappears.
I have tried this on below link but they used Array adapter, So my question is is it possible only in Array adapter or I can used simple adapter?
Android listview edittext filter space button?
If yes then how can I implement, kindly help. Advance thank you.
try this way
searchView.setOnEditorActionListener(new EditText.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
return true;
}
});
addTextChangeListener();
now create method addTextChangeListener
private void addTextChangeListener() {
searchView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence query, int start, int before, int count) {
query = query.toString().trim().toLowerCase();
final ArrayList<CityDataModel> filteredList = new ArrayList<>();
final CharSequence finalQuery = query;
new Thread(new Runnable() {
#Override
public void run() {
// Clear the filter list
filteredList.clear();
// If there is no search value, then add all original list items to filter list
if (TextUtils.isEmpty(finalQuery)) {
filteredList.addAll(cities);
} else {
// Iterate in the original List and add it to filter list...
for (CityDataModel item : cities) {
if (item.getCity_name().toLowerCase().contains(finalQuery.toString().toLowerCase())
) {
// Adding Matched items
filteredList.add(item);
}
}
}
// Set on UI Thread
((Activity) context).runOnUiThread(new Runnable() {
#Override
public void run() {
// Notify the List that the DataSet has changed...
adapter = new SearchCityAdapter(SearchCityClass.this, filteredList);
recyclerSearchCity.setAdapter(adapter);
}
});
}
}).start();
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
You can use any Adapter, you can just implements your adapter with android.widget.Filterable
Example Adapter,
public class AppAdapter extends RecyclerView.Adapter<AppHolder> implements Filterable {
public static final String TAG = AppAdapter.class.getSimpleName();
private ArrayList<App> mApps = new ArrayList<>();
private List<App> mCurrentItmCopy = new ArrayList<>();
private String currentFilter;
private MyArrayFilter mFilter;
#Override
public AppHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View receiverView = LayoutInflater.from(parent.getContext()).
inflate(R.layout.layout_row_apps, parent, false);
return new AppHolder(receiverView);
}
#Override
public void onBindViewHolder(final AppHolder holder, int position) {
final App data = mApps.get(position);
}
#Override
public int getItemCount() {
return mApps.size();
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new MyArrayFilter();
}
return mFilter;
}
private class MyArrayFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mCurrentItmCopy == null || (mCurrentItmCopy.size() == 0)) {
mCurrentItmCopy = new ArrayList<App>(mApps);
}
ArrayList<App> newValues = new ArrayList<App>();
if (prefix != null && !TextUtils.isEmpty(prefix.toString())) {
String prefixString = prefix.toString().toLowerCase();
for (App value : mCurrentItmCopy) {
String label = value.getLabel().toLowerCase();
if ((label.contains(prefixString)) && !newValues.contains(value)) {
newValues.add(value);
}
}
results.values = newValues;
results.count = newValues.size();
} else {
results.values = new ArrayList<App>(mCurrentItmCopy);
results.count = mCurrentItmCopy.size();
mCurrentItmCopy.clear();
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
currentFilter = constraint.toString();
if (results.count > 0) {
mApps.clear();
addAll((ArrayList<App>) results.values);
} else {
mApps.clear();
notifyDataSetChanged();
}
}
}
public void addAll(List<App> items) {
if (items != null) {
mApps.addAll(items);
}
notifyDataSetChanged();
}
}
In the above Adapter instead of App, you can use your object.
You can call from your activity or fragment like this,
mAdapter.getFilter().filter(newText);
This is my Adapter Class for ListView,
Need Help, I am getting original positions, after filtering the listview, instead positions of filtered result. Code is given below, kindly go through it,if any query kindly ask.
// This is my Adapter Class for ListView
public class mAdapter extends BaseAdapter implements Filterable {
ArrayList<MlaData> dats;
public ArrayList<MlaData> filterList;
enter code here
CustomFilter filter;
Context c;
ImageLoader imageLoader;
public mAdapter(Context ctx,ArrayList<MlaData> dats){
this.c=ctx;
this.dats=dats;
this.filterList = dats;
}
#Override
public int getCount() {
return dats.size();
}
#Override
public Object getItem(int position) {
return dats.get(position);
}
#Override
public long getItemId(int position) {
int itemID;
// orig will be null only if we haven't filtered yet:
if (filterList == null)
{
itemID = position;
}
else
{
itemID = dats.indexOf(dats.get(position));
}
return itemID;
}
#Override
public Filter getFilter() {
if(filter==null)
{
filter = new CustomFilter();
}
return filter;
}
class CustomFilter extends Filter{
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint!=null && constraint.length()>0)
{
constraint = constraint.toString().toUpperCase();
ArrayList<MlaData> filters = new ArrayList<MlaData>();
//Filtering
for(int i=0;i<filterList.size();i++)
{
if(filterList.get(i).getName().toUpperCase().contains(constraint)){
MlaData MlaDat = new MlaData(filterList.get(i).getName(),filterList.get(i).getImageUrl(),filterList.get(i).getArea(),filterList.get(i).getId(),filterList.get(i).getEmail());
filters.add(MlaDat);
}
results.count=filters.size();
results.values=filters;
}
}else {
results.count=filterList.size();
results.values=filterList;
}
return results;
}#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
dats=(ArrayList<MlaData>)results.values;
notifyDataSetChanged();
}
}
MainActivity.java
(Only The ListView OnClick Function) :
private ArrayList<MlaData> MlaDats = new ArrayList<MlaData>();
private String MlaNameString, MlaImageString, MlaIdString, MlaEmailString, MlaAreaString;
private GridView listView;
private mAdapter adapt;
private SearchView sv;
listView = (GridView) findViewById(R.id.mldata);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int posi = (int) adapt.getItemId(position);
Intent intent = new Intent(Rajasthan_Mla.this, MainActivity.class);
// int pos = (int) adapt.getItemId(position);
String MLAID = MlaDats.get(posi).getId();
String MLANAME = MlaDats.get(posi).getName();
String MLAEMAIL = MlaDats.get(posi).getEmail();
String MLAIMAGE = MlaDats.get(posi).getImageUrl();
String MLAAREA=MlaDats.get(posi).getArea();
intent.putExtra("MLA_ID", MLAID);
intent.put
Extra("MLA_NAME", MLANAME);
intent.putExtra("MLA_EMAIL", MLAEMAIL);
intent.putExtra("MLA_IMAGE", MLAIMAGE);
intent.putExtra("MLA_AREA", MLAAREA);
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("Mukesh", 0);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("MLAID", MLAID);
editor.putString("MLANAME",MLANAME);
editor.commit();
startActivity(intent);
}
});
DataModel Class :
package com.wdm.mukku.wdm;
public class MlaData {
private String name;
private String imageUrl;
private String area;
private String email;
private String id;
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return imageUrl;
}
public void setImage(String image) {
this.imageUrl = image;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public MlaData(String name,String image,String area,String id,String email) {
this.name=name;
this.imageUrl=image;
this.area=area;
this.id=id;
this.email=email;
}
public MlaData() {
}
}
You can get filtered listview's position by
((ListView) parent).getAdapter().getItem(position)
Example
private ArrayList MlaDats = new ArrayList();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
MlaData mModel = ((ListView) parent).getAdapter().getItem(position);
String id = mModel.getId();
Log.d(TAG,"id = "+id);
}
});
First change this
public mAdapter(Context ctx,ArrayList<MlaData> dats){
this.c=ctx;
this.dats=dats;
// will create a new array instead of referencing to the same object
this.filterList = new ArrayList<MlaData>(dats);
}
Next don't modify dats anymore and only use the filtered list, so you will keep the original list and use that when you filter on something else.
So use this in your filter
// temp array to store filtered data
ArrayList<MlaData> filters = new ArrayList<MlaData>();
// use original list to loop through and check for matches
for (int i = 0; i < dats.size(); i++) {
if (dats.get(i).getName().toUpperCase().contains(constraint)) {
MlaData MlaDat = new MlaData(dats.get(i).getName(), dats.get(i).getImageUrl(), dats.get(i).getArea(), dats.get(i).getId(), dats.get(i).getEmail());
filters.add(MlaDat);
}
}
results.count = filters.size();
results.values = filters;
}
else {
results.count = dats.size();
results.values = dats;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// assign the filtered data to filterList
filterList = (ArrayList<MlaData>)results.values;
notifyDataSetChanged();
}
And finally change your methods to use the filtered list
#Override
public int getCount() {
return filterList.size();
}
#Override
public Object getItem(int position) {
return filterList.get(position);
}
#Override
public long getItemId(int position) {
return ((MlaData)filterList.get(position)).getId();
}
When you clear the filter you should reset the filterList to the original data again
filterList = new ArrayList<MlaData>(dats);
1. Update your adapter's method getItemId() as below:
#Override
public long getItemId(int position) {
return position;
}
2. Update ListView onItemClick() method as below:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MlaData item = MlaDats.get(position);
String MLAID = item.getId();
String MLANAME = item.getName();
String MLAEMAIL = item.getEmail();
String MLAIMAGE = item.getImageUrl();
String MLAAREA = item.getArea();
Intent intent = new Intent(Rajasthan_Mla.this, MainActivity.class);
intent.putExtra("MLA_ID", MLAID);
intent.putExtra("MLA_NAME", MLANAME);
intent.putExtra("MLA_EMAIL", MLAEMAIL);
intent.putExtra("MLA_IMAGE", MLAIMAGE);
intent.putExtra("MLA_AREA", MLAAREA);
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("Mukesh", 0);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("MLAID", MLAID);
editor.putString("MLANAME",MLANAME);
editor.commit();
startActivity(intent);
}
});
I have a DB named RealmItem and I have all users have territories they are attached to. Which is n size unknown. Every item has a field called territory. Now, is there a way to query Realm to find all Item Records that has any of the territoryID attached to the user. The reason I'm in need of this is because, I pipe a AutoCompleteTextView to a filtering adapter that looks like this:
public class ItemFilterAdapter extends BaseAdapter implements Filterable {
private static final String TAG = ItemFilterAdapter.class.getSimpleName();
private Context mContext;
private List<RealmItem> mResult = new ArrayList<>();
private LayoutInflater inflater;
private boolean needsFilter = false;
public ItemFilterAdapter(Context mContext) {
this.mContext = mContext;
}
public void setNeedsFilter(boolean needsFilter) {
this.needsFilter = needsFilter;
}
#Override
public int getCount() {
return mResult.size();
}
#Override
public Object getItem(int position) {
return mResult.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (view == null)
view = inflater.inflate(R.layout.item_update_autocomplete, parent, false);
RealmItem item = mResult.get(position);
TextView updateName = (TextView) view.findViewById(R.id.update_name);
TextView updateAddress = (TextView) view.findViewById(R.id.update_address);
if (item != null) {
updateName.setText(item.getName());
try {
JSONObject obj = new JSONObject(item.getPayload());
String address = obj.getString("address");
updateAddress.setText(address);
} catch (Exception e) {
e.printStackTrace();
}
}
return view;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
return null;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults filterResults) {
if (constraint != null) {
mResult = filterDealers(constraint.toString());
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
}
#NonNull
private List<RealmItem> filterDealers(String query) {
Realm mRealm = RealmUtils.getRealmInstance(mContext);
if (!needsFilter) {
return mRealm.where(RealmItem.class)
.contains("name", query, Case.INSENSITIVE)
.equalTo("id", [array of Ids]) <-- This is where I need it
.findAll();
} else {
return mRealm.where(RealmItem.class)
.contains("name", query, Case.INSENSITIVE)
.notEqualTo("activeStatus", "inactive")
.equalTo("id", [array of Ids]) <-- This is where I need it
.findAll();
}
}
}
More like looking for something like this .equalTo("id", [array of Ids]) <-- This is where I need it or anything nice to make filtering seemlessly smooth 😉
Aren't you basically just looking for the in() operator, added in 1.1.0?
public RealmQuery<E> in(
String fieldName, Integer[] values)
I'm trying to implement filtering of a ListView which is uses a custom object adapter, but I can't find any useful samples. The included code is very simplified, so no- keep in mind I can't use an regular ArrayAdapter.
I have a EditText above the ListView, and when the user enters text in the EditText widget I would like to filter the ListView by the text written in the EditText.
Any suggestions would be much appreciated!
Here is the snippet from the activity class:
public class management_objects extends Activity {
private static List<User> UserList;
private EfficientAdapter adapter = null;
private ListView objectListView = null;
private EditText SearchText = null;
private static class EfficientAdapter extends BaseAdapter implements Filterable{
private LayoutInflater mInflater;
public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return UserList.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.imagelayout_2lines, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.managementObjectText);
holder.subtext = (TextView) convertView.findViewById(R.id.managementObjectSubText);
holder.icon = (ImageView) convertView.findViewById(R.id.managementObjectIcon);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(UserList.get(position).getFirstName());
holder.subtext.setText(UserList.get(position).getLastName());
holder.icon.setImageResource(R.drawable.user);
return convertView;
}
static class ViewHolder {
TextView text;
TextView subtext;
ImageView icon;
}
#Override
public Filter getFilter() {
return null;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.adobjectlist);
Bundle extras = getIntent().getExtras();
SearchText = (EditText) findViewById(R.id.SearchBox);
SearchText.addTextChangedListener(filterTextWatcher);
objectListView = (ListView) findViewById(R.id.ObjectList);
objectListView.setOnItemClickListener(Item_Click);
adapter = new EfficientAdapter(this);
ComputerName = extras.getString("COMPUTER_NAME");
//Get User list from webservice
ShowUsers();
}
Here is The User class:
public class User {
private int UserId;
private String FirstName;
private String LastName;
public int getUserId() {
return UserId;
}
public void setUserId(int UserId) {
this.UserId = UserId;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String FirstName) {
this.FirstName = FirstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String LastName) {
this.LastName = LastName;
}
}
You need to do a few things:
1) In your activity, register for a text change listener on your EditText that contains the value the user enters:
mSearchValue.addTextChangedListener(searchTextWatcher);
2) Create your searchTextWatcher and have it do something:
private TextWatcher searchTextWatcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// ignore
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// ignore
}
#Override
public void afterTextChanged(Editable s) {
Log.d(Constants.TAG, "*** Search value changed: " + s.toString());
adapter.getFilter().filter(s.toString());
}
};
3) Override getFilter() in your custom adapter and have it filter the results and notify the listview that the dataset has changed.
#Override
public Filter getFilter() {
return new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
Log.d(Constants.TAG, "**** PUBLISHING RESULTS for: " + constraint);
myData = (List<MyDataType>) results.values;
MyCustomAdapter.this.notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
Log.d(Constants.TAG, "**** PERFORM FILTERING for: " + constraint);
List<MyDataType> filteredResults = getFilteredResults(constraint);
FilterResults results = new FilterResults();
results.values = filteredResults;
return results;
}
};
}
Here an interesting example
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oReturn = new FilterResults();
final ArrayList<station> results = new ArrayList<station>();
if (orig == null)
orig = items;
if (constraint != null) {
if (orig != null && orig.size() > 0) {
for (final station g : orig) {
if (g.getName().toLowerCase()
.contains(constraint.toString()))
results.add(g);
}
}
oReturn.values = results;
}
return oReturn;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
items = (ArrayList<station>) results.values;
notifyDataSetChanged();
}
};
}
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
notifyChanged = true;
}
For those who don't need the Filterable interface, there is a much simpler solution. This also handles notifyDataSetChanged() correctly where the other solutions fail. Note that you need to add a getArray() function to the BaseAdapter that just returns the array object that was passed to the constructor.
public abstract class BaseFilterAdapter<T> extends BaseAdapter<T> {
private List<T> original;
private String lastFilter;
public BaseFilterAdapter(Context context, List<T> array) {
super(context, new LinkedList<T>());
original = array;
filter("");
}
protected abstract Boolean predicate(T element, String filter);
public void filter(String filter) {
lastFilter = filter;
super.getArray().clear();
for (T element : original)
if (predicate(element, filter))
super.getArray().add(element);
super.notifyDataSetChanged();
}
#Override
public List<T> getArray() {
return original;
}
#Override
public void notifyDataSetChanged() {
filter(lastFilter);
}
}
Add toString override on your base class. For example
#Override
public String toString() {
return this.name;
}
Above makes your List as string list. So you can use:
your_edit_text.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
YourActivity.this.YourAdapter.getFilter().filter(arg0);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
#Override
public void afterTextChanged(Editable arg0) {
}
});