Android AutoCompleteTextView Refreshing - java

I am using Geocoder to fetch matching addresses from a String.
I am trying to display the returned addresses to an AutoCompleteTextView.
I can see the values properly when I Log.i("Result:"," "+list_of_addresses);
Since we are talking about dynamic list loading I am calling adapter.NotifyDataSetChanged();
I am using addTextChangedListener to listen to the changes in the text input by the user
This is what the code looks like
public class Map extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
final Geocoder gc = new Geocoder(getApplicationContext(), Locale.getDefault());
final ArrayList<String> address_name = new ArrayList<String>();
final AutoCompleteTextView search = (AutoCompleteTextView) findViewById(R.id.search);
search.setThreshold(1);
final ArrayAdapter<String> adapter =new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line,address_name);
search.setAdapter(adapter); //moved this line out of the try block
search.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
List<Address> list = null;
Address address = null;
try {
list = gc.getFromLocationName(s.toString(), 10);
Log.i("List:", ""+list); //CAN see this log
} catch (IOException e) {
e.printStackTrace();
}
for(int i=0; i<list.size(); i++){
address = list.get(i);
address_name.add(address.getFeatureName().toString());
Log.i("Address: ", address.getFeatureName().toString()); //CANto see this Log
}
if(!list.isEmpty()){
list.clear();
}
adapter.notifyDataSetChanged();
search.showDropDown();
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
});
}
}
Inside the for loop I am unable to see the log.i("Addresses:",address.getFeatureName.toString());
But when i change the for loop condition to i<=list.size() I do get the Log output but the application forcecloses with this error java.lang.IndexOutOfBoundsException: Invalid index 10, size is 10
Maybe that's why I am unable to see the Address list?
EDIT: I changed the for loop condition to i<list.size() also added search.showDropDown() after notifying dataset changed.
Any help would be appreciated! Thankyou.

You seem to have a problem with getting it to work. I'll paste what works for me really well, only relevant sections for AutoComplete.
onCreate
pickUpAutoComplete = new AutoComplete(this, R.layout.pickupautocomplete);
pickUpAutoComplete.setNotifyOnChange(true);
locationText = (AutoCompleteTextView) findViewById(R.id.locationText);
locationText.setOnItemClickListener(this);
locationText.setOnFocusChangeListener(this);
locationText.setAdapter(pickUpAutoComplete);
layout xml
<AutoCompleteTextView
android:id="#+id/locationText"
style="#style/registerLargestTextSize"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_margin="10dp"
android:layout_weight="6"
android:background="#ffffff"
android:completionThreshold="3"
android:focusable="true"
android:gravity="center"
android:hint="home location"
android:lines="3"
android:maxLines="3"
android:minLines="3"
android:paddingBottom="3dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbarStyle="outsideOverlay"
android:textColor="#b2b2b2"
android:textStyle="bold" />
AutoComplete Class, Don't forget to replace your API KEY
public class AutoComplete extends ArrayAdapter<String> implements Filterable {
private static final String LOG_TAG = "carEgiri";
private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
private static final String OUT_JSON = "/json";
private static final String API_KEY = "**YOUR API KEY HERE**";
private ArrayList<String> resultList;
public AutoComplete(IPostAutoCompleteUIChange context,
int textViewResourceId) {
super((Context) context, textViewResourceId);
}
#Override
public int getCount() {
if (resultList == null)
return 0;
return resultList.size();
}
#Override
public String getItem(int index) {
return resultList.get(index);
}
#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;
}

The problem is related to a wrong or empty override of adapter methods:
#Override
public UPorPackageItem getItem(int index) {
return mValues.get(index);
}
#Override
public int getCount() {
if (mValues == null)
return 0;
return mValues.size();
}
you must implement the above method.
It will works

Related

Showing list of elements in recyclerView failed

I am trying to make a news app, data obtained from RSS feed. I get xml response from the feed. And I am using XmlPullParser to parse the xml. The parsing is a success. I can see the values in my log.
But somehow I am not able to fill them in my recyclerView. It's all just blank. My java class is:
public class RssNewsActivity extends AppCompatActivity {
private static final String TAG = RssNewsActivity.class.toString();
RssFeedAdapter adapter;
RecyclerView recyclerView_rssFeed;
SwipeRefreshLayout swipeRefreshLayout;
private List<RssModel> listResponseModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rss_news);
initialize();
recyclerView_rssFeed.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView_rssFeed.setLayoutManager(linearLayoutManager);
adapter = new RssFeedAdapter(RssNewsActivity.this, listResponseModel);
recyclerView_rssFeed.setAdapter(adapter);
fetchNewsFeed();
//if user swipes the recycler then refresh content page
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
fetchNewsFeed();
}
});
}
private void initialize() {
swipeRefreshLayout = findViewById(R.id.swipeRefresh_rssFeed);
recyclerView_rssFeed = findViewById(R.id.recyclerView_rssFeed);
listResponseModel = new ArrayList<>();
}
private void fetchNewsFeed() {
String url = "here is my news feed url";
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
listResponseModel.clear();
try {
listResponseModel = parseNewsFeed(response);
} catch (XmlPullParserException | IOException e) {
Log.e(TAG, e.getMessage());
}
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(request);
}
private List<RssModel> parseNewsFeed(String response) throws XmlPullParserException,
IOException {
XmlPullParserFactory parserFactory = XmlPullParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
XmlPullParser xmlPullParser = parserFactory.newPullParser();
xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xmlPullParser.setInput(new StringReader(response));
return processParsing(xmlPullParser);
}
private List<RssModel> processParsing(XmlPullParser xmlPullParser) throws IOException, XmlPullParserException {
List<RssModel> listRssFeed = new ArrayList<>();
int eventType = xmlPullParser.getEventType();
RssModel rssModel = null;
xmlPullParser.nextTag();
while (eventType != XmlPullParser.END_DOCUMENT) {
String eltName;
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
eltName = xmlPullParser.getName();
if ("item".equals(eltName)) {
rssModel = new RssModel();
} else if (rssModel != null) {
if ("title".equals(eltName)) {
String title = xmlPullParser.nextText();
rssModel.setTitle(title);
Log.d(TAG, "title: " + title);
} else if ("link".equals(eltName)) {
String link = xmlPullParser.nextText();
rssModel.setLink(link);
Log.d(TAG, "link: " + link);
}
}
break;
case XmlPullParser.END_TAG:
eltName = xmlPullParser.getName();
if ("item".equals(eltName) && rssModel != null) {
listRssFeed.add(rssModel);
}
break;
}
eventType = xmlPullParser.next();
}
return listRssFeed;
}
}
my xml design is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="rssnewsfeed.RssNewsActivity">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeRefresh_rssFeed"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView_rssFeed"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
This is my adapter class
public class RssFeedAdapter extends RecyclerView.Adapter<RssFeedAdapter.RssViewHolder> {
private Context mContext;
private List<RssModel> mRssFeeds;
public RssFeedAdapter(Context mContext, List<RssModel> mRssFeeds) {
this.mContext = mContext;
this.mRssFeeds = mRssFeeds;
}
#NonNull
#Override
public RssViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(mContext).inflate(R.layout.rss_feed_layout, viewGroup, false);
return new RssViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull RssViewHolder rssViewHolder, int i) {
RssModel post = mRssFeeds.get(i);
rssViewHolder.textView_title.setText(post.getTitle());
rssViewHolder.textView_link.setText(post.getLink());
}
#Override
public int getItemCount() {
return mRssFeeds.size();
}
public class RssViewHolder extends RecyclerView.ViewHolder {
private TextView textView_title, textView_link;
public RssViewHolder(#NonNull View itemView) {
super(itemView);
textView_title = itemView.findViewById(R.id.textView_title);
textView_link = itemView.findViewById(R.id.textView_link);
}
}
}
And finally this is my model class:
public class RssModel {
private String title;
private String link;
public RssModel() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
I tried many ways but no success. I don't know what I am missing. I will be grateful for any guidance. Thanks.
Giving " = " will create a new instance of ArrayList apart from which is already binded to RecyclerView adapter.
So, you need to change this,
listResponseModel = parseNewsFeed(response);
to
listResponseModel.addAll(parseNewsFeed(response));
This happens because the Rss list which you're passing to recycler view adapter is null as you mentioned earlier you're successfully getting the values in log so another guaranteed workaround is to set the values into an separate arraylist.
So inside your class simply create arraylist:
private ArrayList<String> title;
private ArrayList<String> post;
This will be your initialize method:
private void initialize()
{
swipeRefreshLayout = findViewById(R.id.swipeRefresh_rssFeed);
recyclerView_rssFeed = findViewById(R.id.recyclerView_rssFeed);
title = new ArrayList<>();
post = new ArrayList<>();
}
Now simply pass your values to arraylist:
title.add(title)
post.add(post)
Now pass those arraylist to adapter:
adapter = new RssFeedAdapter(RssNewsActivity.this, title,post);
recyclerView_rssFeed.setAdapter(adapter);
After this initialize arraylist in adapter and fetch your values!
One more Important thing inside your oncreate() place your fetchNewsFeed(); method before initializing the adapter
initialize();
fetchNewsFeed();
recyclerView_rssFeed.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView_rssFeed.setLayoutManager(linearLayoutManager);
adapter = new RssFeedAdapter(RssNewsActivity.this, listResponseModel);
recyclerView_rssFeed.setAdapter(adapter);

Filter an Object in BaseAdapter

I'm new in Android programming and I want to create a custom Filter in my Baseadapter.
Honestly it's kinda confusing when I check the other questions because they mostly use Arraylists. I already created a custom View (getView) that sets small pictogramms into my ListView. I already tried many ways to implement these custom Filter from Arraylist examples, but somehow I get into a blockade.
It would be very helpful if someone could atleast give me some direction for a Custom Filter with Objects
cryptoListAdapter.java
public class cryptoListAdapter extends BaseAdapter {
private Context context;
LayoutInflater mInlfater;
ArrayList<HashMap<String,String>> currencyList;
TextView name;
// Constructor
public cryptoListAdapter(Context context,ArrayList<HashMap<String,String>> currencyList)
{
mInlfater = LayoutInflater.from(context);
this.currencyList = currencyList;
}
#Override
public int getCount() {
return currencyList.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) {
cryptoPicto cp = new cryptoPicto();
View newView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_crypto_items, null);
name = (TextView) newView.findViewById(R.id.name);
TextView symbol = (TextView) newView.findViewById(R.id.symbol);
ImageView image_list_icon = (ImageView)newView.findViewById(cryptopicto);
//cp.createFinalFileName(name);
HashMap<String, String> map;
map = currencyList.get(position);
name.setText(map.get("name"));
symbol.setText(map.get("symbol"));
Picasso.with(newView.getContext()).load(map.get("cryptopicto")).into(image_list_icon);
return newView;
}
currencyTableView.java
public class currencyTableView extends AppCompatActivity {
private String TAG = currencyTableView.class.getSimpleName();
private ProgressDialog pDialog;
private ListView lv;
private SearchView sv;
private ImageView im;
private static String url = "https//myURLToJSON";
Context context;
cryptoListAdapter adapter;
ArrayList<HashMap<String, String>> currencyList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_currency_table_view);
sv = (SearchView) findViewById(R.id.search_currency);
currencyList = new ArrayList<>();
lv = (ListView) findViewById(R.id.list);
im = (ImageView) findViewById(R.id.cryptopicto);
new GetCurrencies().execute();
}
// URL to get currencies JSON
private class GetCurrencies extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(currencyTableView.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
databasehandler sh = new databasehandler();
cryptoPicto cp = new cryptoPicto();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONArray jsonArray = new JSONArray(jsonStr);
// looping through currencies
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject c = jsonArray.getJSONObject(i);
String name = c.getString("name");
String symbol = c.getString("symbol");
Double price_usd = c.getDouble("price_usd");
Double price_eur = c.getDouble("price_eur");
Double price_btc = c.getDouble("price_btc");
Double volume_eur = c.getDouble("volume_eur");
Double market_cap_usd = c.getDouble("market_cap_usd");
Double percent_change_1h = c.getDouble("percent_change_1h");
Double percent_change_24h = c.getDouble("percent_change_24h");
Double percent_change_7d = c.getDouble("percent_change_7d");
// tmp hash map for single currency
HashMap<String, String> currency = new HashMap<>();
// create Path to picto Filename
cp.createFinalFileName(name);
// adding each child node to HashMap key => value
currency.put("cryptopicto", cp.getFinalFileName());
currency.put("name", name);
currency.put("symbol", symbol);
// adding currency to currencyList
currencyList.add(currency);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Couldn't get json from server. Check LogCat for possible errors!",
Toast.LENGTH_LONG)
.show();
}
});
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updating parsed JSON data into ListView
* */
adapter = new cryptoListAdapter(
currencyTableView.this, currencyList) {
};
lv.setAdapter(adapter);
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String currencyList) {
adapter.getFilter().filter(currencyList);
return false;
}
});
}
}
}
Thanks in Advance :)
Make your BaseAdapder implements Filterable
then add
List<HashMap<String,String>> mOriginalValues;
after
ArrayList<HashMap<String,String>> currencyList;
in your adapter class
and then add this method at the bottom before the closing braces "}"
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
currencyList = (ArrayList<HashMap<String,String>>) results.values;
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
ArrayList<HashMap<String, String>> FilteredArrList = new ArrayList<HashMap<String, String>>();
if (mOriginalValues == null) {
mOriginalValues = new ArrayList<HashMap<String, String>>(currencyList); // saves
}
if (constraint == null || constraint.length() == 0) {
// set the Original result to return
results.count = mOriginalValues.size();
results.values = mOriginalValues;
} else {
Locale locale = Locale.getDefault();
constraint = constraint.toString().toLowerCase(locale);
for (int i = 0; i < mOriginalValues.size(); i++) {
HashMap<String, String> currency = mOriginalValues.get(i);
String data = currency.get("name");
if (data.toLowerCase(locale).startsWith(constraint.toString())) {
FilteredArrList.add(currency);
}
}
// set the Filtered result to return
results.count = FilteredArrList.size();
results.values = FilteredArrList;
}
return results;
}
};
return filter;
}
Let me know if that helps

How to compare originalList to filterList in recyclerview using Filter?

In this code I have search multiple text ex. I have search sachin.
sachin is show the list but click to back sachin to sac not display to sa list on adapter. How to solve it without any library?
when I press back space and remove a char this time dos not list not display.
Example
Suppose I have search sachin to text change sachin to sac. In this case not display sa list. I have clear all list that case display all list.
search sa show the list
sachin and sardar
now search sac
now display the sachin
search only sac to sc
that's time display only sachin
not disply the sardar in the list
My Adapter
private class ItemFilter extends Filter {
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<Build> buildlist = new ArrayList<Build>();
for (int i = 0; i < buildList.size(); i++) {
if ((buildList.get(i).getName().toUpperCase())
.contains(constraint.toString().toUpperCase())) {
Build babydata = new Build(buildList.get(i).getImages(), buildList.get(i).getName());
buildlist.add(babydata);
}
}
results.count = buildlist.size();
results.values = buildlist;
} else {
results.count = buildList.size();
results.values = buildList;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
buildList = (ArrayList<Build>) results.values;
notifyDataSetChanged();
}
}
Activity class
EditText editTxt = (EditText) findViewById(R.id.search);
editTxt.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length() <= 0) {
Log.d("jay", "s.length() <= 0" + s.toString());
buildList.clear();
buildList.addAll(buildListCopy);
recyclerView.setAdapter(null);
buildCustomAdapter = new BuildCustomAdapter(buildList);
recyclerView.setAdapter(buildCustomAdapter);
} else {
buildCustomAdapter.getFilter().filter(s.toString());
}
Log.d("jay", "mobisharnam" + s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
Without any Library simple logic
Finally I have solution in this question
In your Adapter Constructor add the new copy list
After the copy list is add in filter
private List<YourModel> modelList;
private List<YourModel> modelListCopy;
private ItemFilter mFilter = new ItemFilter();
public YourAdapter(List<YourModel> modelList) {
this.modelList= modelList;
this.modelListCopy= new ArrayList<>();
modelListCopy.addAll(modelList);
}
private class ItemFilter extends Filter {
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
List<YourModel> filterList = new ArrayList<YourModel>();
for (int i = 0; i < modelListCopy.size(); i++) {
if ((modelListCopy.get(i).getName().toUpperCase())
.contains(constraint.toString().toUpperCase())) {
YourModel builddata = new YourModel(modelListCopy.get(i).getImages(), modelListCopy.get(i).getName());
filterList.add(builddata);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = modelListCopy.size();
results.values = modelListCopy;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
modelList= (ArrayList<YourModel>) results.values;
notifyDataSetChanged();
}
Activity Class
like this
CustomAdapter youradapter= new CustomAdapter(modelList);
I prefer Predicate for search filter
I have changed your code to use Predicate, You have to use google guava library for that
include following depedency in your gradle
compile 'com.google.guava:guava:19.0'
now, check following code
EditText editTxt = (EditText) findViewById(R.id.search);
editTxt.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String searchQuery = s.toString();
if (buildListCopy != null && buildListCopy.size() > 0) {
buildList = Lists.newArrayList(Collections2.filter(buildListCopy, new SearchFilter(searchQuery)));
recyclerView.setAdapter(null);
if (buildList != null && buildList.size() > 0) {);
buildCustomAdapter = new BuildCustomAdapter(buildList);
recyclerView.setAdapter(buildCustomAdapter);
recyclerView.getAdapter().notifyDataSetChanged();
}
}
return false;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
Here is your search filter predicate which we have used above
/**
* Custom Predicate class to filter list as per search query
*/
public final class SearchFilter implements Predicate<Build> {
private final Pattern pattern;
public SearchFilter(final String regex) {
pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.LITERAL);
}
#Override
public boolean apply(final Build input) {
return pattern.matcher(input.getName().toLowerCase()).find();
}
}

Set Json Array values to AutoCompleteTextView in Android

I am new in Android development, I want to bind a Json array to android AutocompleteTextView in Form (Registration form).
the Json array is showed in below
{"Status":true,"errorType":null,"InstituteList":[{"InstituteID":"1","InstituteName":"Demo Institute"},{"InstituteID":"16","InstituteName":"Sheridan College"},{"InstituteID":"17","InstituteName":"iCent Prosp"},{"InstituteID":"18","InstituteName":"Seneca College"}]}
here the Type Institution Name is the auto completeTextView. The main requirement is that, I can bind the values like in the Json response InstituteName on the front end and When click on the Submit Button it needs to take the InstituteID Object.
Currently I can bind the InstituteName Object to AutocompleteTextView and Working fine.
But the Submit Action was not performing perfectly.
I cant getting the InstituteID in my codes for performing
Here is my code.
Getting response from web service as json array and binding in asyncTask.
#Override
protected void onPostExecute(String res) {
try
{
Log.i("Intitute List",res);
JSONObject responseObject = new JSONObject(res);
String status=responseObject.getString("Status");
ArrayList<String> listInstituteNames = new ArrayList<>();
JSONArray detailsArray = responseObject.getJSONArray("InstituteList");
for (int i = 0; i <detailsArray.length() ; i++) {
JSONObject obj = detailsArray.getJSONObject(i);
listInstituteNames.add(obj.getString("InstituteName"));
}
//Log.i("InstituteName", String.valueOf(listInstituteNames));
myStringArray = listInstituteNames;
AutoCompleteAdapter adapter = new AutoCompleteAdapter(SignUpActivity.this, android.R.layout.simple_dropdown_item_1line, android.R.id.text1, listInstituteNames);
autoTextView.setThreshold(1);
autoTextView.setAdapter(adapter);
}
catch (JSONException e1) {
e1.printStackTrace();
}
AutoCompleteAdapter.java
package Adapter;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> fullList;
private ArrayList<String> mOriginalValues;
private ArrayFilter mFilter;
public AutoCompleteAdapter(Context context, int resource, int textViewResourceId, List<String> objects) {
super(context, resource, textViewResourceId, objects);
fullList = (ArrayList<String>) objects;
mOriginalValues = new ArrayList<String>(fullList);
}
#Override
public int getCount() {
return fullList.size();
}
#Override
public String getItem(int position) {
return fullList.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return super.getView(position, convertView, parent);
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
private Object lock;
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (lock) {
mOriginalValues = new ArrayList<String>(fullList);
}
}
if (prefix == null || prefix.length() == 0) {
synchronized (lock) {
ArrayList<String> list = new ArrayList<String>(mOriginalValues);
results.values = list;
results.count = list.size();
}
} else {
final String prefixString = prefix.toString().toLowerCase();
ArrayList<String> values = mOriginalValues;
int count = values.size();
ArrayList<String> newValues = new ArrayList<String>(count);
for (int i = 0; i < count; i++) {
String item = values.get(i);
if (item.toLowerCase().contains(prefixString)) {
newValues.add(item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(results.values!=null){
fullList = (ArrayList<String>) results.values;
}else{
fullList = new ArrayList<String>();
}
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
AutoCompleteTextView Section in XML File..
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:id="#+id/autoCompt"
android:orientation="vertical">
<AutoCompleteTextView
android:id="#+id/instname_field"
android:layout_width="match_parent"
android:hint="Type Institution Name"
android:paddingLeft="10dp"
android:textColor="#fff"
android:background="#b8d1e5"
android:layout_height="40dp"
android:textSize="20dp"
android:ems="10"/>
</LinearLayout>
How can I solve this Issue. Thanks.
You can see #blackBelt comment that is the right way to do that.
But here i am explain you another method which is easy to understand using Hashmap instead of Object class .
HashMap<String, String> map_name_value = new HashMap<String, Stirng>();
for (int i = 0; i <detailsArray.length() ; i++) {
JSONObject obj = detailsArray.getJSONObject(i)
listInstituteNames.add(obj.getString("InstituteName"))
map_name_value.put(obj.getString("InstituteName"),obj.getString("InstituteID"));
}
Then while clicking the item.
Do this:
autoTextView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View arg1, int pos,
long id) {
Editable message = autoTextView.getText();
String item_name = message.toString();
String item_id = map_name_value.get(item_name);
//your stuff
}
});
//item_name is name of institute
// item_id is id of institute

how to make autocomplete or autosuggest in android?

I have make a demo of auto suggest . I have name(string) and code(string) .I have around 2000 name with their codes ..So I take string array and put it in this format name-(code) example "Alexandra Palace-(AAP)",.my problem is that I need to filter using code not by name .Actually when I type in input field it match with name not with code .But I need to filter with code.
example
when I type "lwy" it will not show "MNCRLWY-(LWY)", can you please tell how I will achieve this ?
I try like this
public class GlobalList {
public static String[] stationList={
"MNCRLWY-(LWY)",
"Lympstone Commando-(LYC)",
"Lydney-(LYD)",
"Lye-(LYE)",
"Lympstone Village-(LYM)",
"Lymington Pier-(LYP)",
"Lymington Town-(LYT)",
"Lazonby & Kirkoswald-(LZB)",
"Leeds, Whitehall (Bus)-(LZZ)",
"Macclesfield-(MAC)",
"Maghull-(MAG)",
"Maidenhead-(MAI)",
"Malden Manor-(MAL)",
"Manchester Piccadilly-(MAN)",
"Martins Heron-(MAO)",
"Margate-(MAR)",
"Manors-(MAS)",
"Matlock-(MAT)",
"Mauldeth Road-(MAU)",
"Mallow-(MAW)",
"Maxwell Park-(MAX)",
"Maybole-(MAY)",
"Millbrook (Hampshire)-(MBK)",
"Middlesbrough-(MBR)",
"Moulsecoomb-(MCB)",
"Metro Centre-(MCE)",
"March-(MCH)",
"Marne La Vallee-(MCK)",
"Morecambe-(MCM)",
"Machynlleth-(MCN)",
"Manchester Oxford Road-(MCO)",
"Manchester Victoria-(MCV)",
"Maidstone Barracks-(MDB)",
"Maidstone East-(MDE)",
"Midgham-(MDG)",
"Middlewood-(MDL)",
"Maiden Newton-(MDN)",
"Morden South-(MDS)",
"Maidstone West-(MDW)",
"MAERDY-(MDY)",
"Meols Cop-(MEC)",
"Meldreth-(MEL)",
"Menheniot-(MEN)",
"Meols-(MEO)",
"Meopham-(MEP)",
"Merthyr Tydfil-(MER)",
"Melton-(MES)",
"Merthyr Vale-(MEV)",
"Maesteg (Ewenny Road)-(MEW)",
"Mexborough-(MEX)",
"Merryton-(MEY)",
"Morfa Mawddach-(MFA)",
"Minffordd-(MFD)",
"Minffordd-(MFF)",
"Milford Haven-(MFH)",
};
}
CustomAdapter :
public class CustomAutocompletAdapter extends BaseAdapter implements Filterable{
private String stationNameAndCodeValue ;
ArrayList<String> autolistArray;
ArrayList<String> objects;
private Context context;
public CustomAutocompletAdapter( Context context, String[] autolistArray){
this.autolistArray=new ArrayList<String>();
for(int i=0;i<autolistArray.length;i++){
this.autolistArray.add(autolistArray[i]);
} this.context = context;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return autolistArray.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return autolistArray.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v = convertView;
if (v == null) {
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = mInflater.inflate(R.layout.custom_row_adapter, null);
}
final TextView stationNameAndCode = (TextView) v
.findViewById(R.id.item_selectStationName);
stationNameAndCodeValue = autolistArray.get(position);
stationNameAndCode.setText(stationNameAndCodeValue);
return v;
}
#Override
public Filter getFilter() {
// TODO Auto-generated method stub
Filter myFilter = new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
System.out.println("Constraint " + constraint);
Log.d("-----------", "publishResults");
if (results.count > 0 && results != null) {
objects = (ArrayList<String>) results.values;
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
Log.d("-----------", "performFiltering");
FilterResults results = new FilterResults();
List<String> FilteredArrList = new ArrayList<String>();
if (objects == null) {
objects = new ArrayList<String>(autolistArray); // saves
}
Locale locale = Locale.getDefault();
constraint = (String) constraint
.toString().toLowerCase(locale);
if (constraint == null || constraint.length() == 0) {
// set the Original result to return
results.count = objects.size();
results.values = objects;
} else {
for (int i = 0; i < objects.size(); i++) {
String name= objects.get(i);
String newName = name.substring(name.indexOf('('),name.length()-1);
if (newName.toLowerCase(locale).contains(constraint))
{
FilteredArrList.add(name);
}
}
// set the Filtered result to return
results.count = FilteredArrList.size();
results.values = FilteredArrList;
}
return results;
}
#Override
public CharSequence convertResultToString(Object resultValue) {
// TODO Auto-generated method stub
//convert object to string
Log.d("-----------", "convertResultToString");
return "";
}
};
return myFilter;
}
}
Main Activity :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.select_station);
autocompleteView = (AutoCompleteTextView) findViewById(R.id.item_autoComplete);
STATION_LIST = new String[GlobalList.stationList.length
+ GlobalExtendStationList.stationList.length];
System.arraycopy(GlobalList.stationList, 0, STATION_LIST, 0,
GlobalList.stationList.length);
System.arraycopy(GlobalExtendStationList.stationList, 0,
STATION_LIST, GlobalList.stationList.length,
GlobalExtendStationList.stationList.length);
autosuggestAdapter = new CustomAutocompletAdapter(this,STATION_LIST);
autocompleteView.setAdapter(autosuggestAdapter);
Xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity=""
>
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Choose station"
android:layout_marginLeft="20dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
<AutoCompleteTextView
android:id="#+id/item_autoComplete"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:ems="10"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:text="AutoCompleteTextView" >
<requestFocus />
</AutoCompleteTextView>
</LinearLayout>
</LinearLayout>
As you are checking the searching string in the whole string(name), so if it founds the serching string anywhere in the name then it adds to the resut.
So Use this
String newName = name.subString(indexOf('('),name.lastIndexOf(')'));
if (newName.toLowerCase(locale).contains(constraint))
{
FilteredArrList.add(name);
}
instead of
if (name.toLowerCase(locale).contains(constraint))
{
FilteredArrList.add(name);
}

Categories