AutoCompleteTextView not showing any drop down items - android

My XML:
<AutoCompleteTextView
android:id="#+id/searchAutoCompleteTextView_feed"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:completionThreshold="2"
android:hint="#string/search" />
MY java code:
AutoCompleteTextView eT = (AutoCompleteTextView)findViewById(R.id.searchAutoCompleteTextView_feed);
eT.addTextChangedListener(this);
String[] sa = new String[]{"apple", "mango", "banana", "apple mango", "mango banana"};
ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line, sa);
eT.setAdapter(aAdapter);
This is not working atall....i mean its just working like an EditTextView. Where am i wrong??
complete code:
public class FeedListViewActivity extends ListActivity implements TextWatcher{
private AutoCompleteTextView eT;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.feed);
eT = (AutoCompleteTextView) findViewById(R.id.searchAutoCompleteTextView_feed);
eT.addTextChangedListener(this);
Thread thread = new Thread(null, loadMoreListItems);
thread.start();
}
private Runnable returnRes = new Runnable() {
public void run() {
//code for other purposes
}
};
private Runnable loadMoreListItems = new Runnable() {
public void run() {
getProductNames();
// Done! now continue on the UI thread
runOnUiThread(returnRes);
}
};
protected void getProductNames() {
String[] sa = new String[]{"apple", "mango", "banana", "apple mango", "mango banana"};
ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_dropdown_item_1line, sa);
eT.setAdapter(aAdapter);
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
}

I just saw your other question before seeing this one. I was struggling with autocomplete for some time and I almost reverted to your new implementation of downloading all the keywords until I finally got it to work. What I did was;
//In the onCreate
//The suggestArray is just a static array with a few keywords
this.suggestAdapter = new ArrayAdapter<String>(this, this.suggestionsView, suggestArray);
//The setNotifyOnChange informs all views attached to the adapter to update themselves
//if the adapter is changed
this.suggestAdapter.setNotifyOnChange(true);
In my textwatcher's onTextChanged method, I get the suggests using an asynctask
//suggestsThread is an AsyncTask object
suggestsThread.cancel(true);
suggestsThread = new WertAgentThread();
suggestsThread.execute(s.toString());
In the AsyncTask's onPostExecute I then update the autocompletetextview
//suggestions is the result of the http request with the suggestions
this.suggestAdapter = new ArrayAdapter<String>(this, R.layout.suggestions, suggestions);
this.suggestions.setAdapter(this.suggestAdapter);
//notifydatasetchanged forces the dropdown to be shown.
this.suggestAdapter.notifyDataSetChanged();
See setNotifyOnChange and notifyDataSetChanged for more information

this is a snippet from my project. I think after you got data from services all you have to do is to:
clear your previous data.
clear the previous adapter values.
then add values to your list of data using add() or addAll() method.
notify the data changed by calling notifyDataSetChanged() on adapter.
#Override
public void onGetPatient(List<PatientSearchModel> patientSearchModelList) {
//here we got the raw data traverse it to get the filtered names data for the suggestions
stringArrayListPatients.clear();
stringArrayAdapterPatient.clear();
for (PatientSearchModel patientSearchModel:patientSearchModelList){
if (patientSearchModel.getFullName()!=null){
stringArrayListPatients.add(patientSearchModel.getFullName());
}
}
//update the array adapter for patient search
stringArrayAdapterPatient.addAll(stringArrayListPatients);
stringArrayAdapterPatient.notifyDataSetChanged();
}
but before all this make sure you have attached the adapter to the auto complete textview if don't do it as follows:
ArrayAdapter<String> stringArrayAdapterPatient= new ArrayAdapter<String>(getActivity(),android.support.v7.appcompat.R.layout.select_dialog_item_material,stringArrayListPatients);
completeTextViewPatient.setAdapter(stringArrayAdapterPatient);

Use adapter.notifyDataSetChanged() method to notify the changes in the list, If that is not working then you can show DropDown manually like autoCompleteTextView.showDropDown()

AutoCompleteTextView eT = (AutoCompleteTextView)findViewById(R.id.searchAutoCompleteTextView_feed);
// eT.addTextChangedListener(this);
String[] sa = new String[]{"apple", "mango", "banana", "apple mango", "mango banana"};
ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line, sa);
eT.setAdapter(aAdapter);
its working just comment on et.addtext line...

The only working solution after updating adapter and notifying about changes instantly show dropDown is reseting AutoCompleteTextView text again, Kotlin example:
with(autoCompleteTextView) {
text = text
// Place cursor to end
}
Java something like:
autoCompleteTextView.setText(autoCompleteTextView.getText());
// Place cursor to end

AutoCompleteTextView.Invalidate()
will do it.

If anyone is using a custom object array list, and facing this issue, check your model class and see if you have override the correct variable in toString. Overriede toString if you have not override yet.
public class MyModalClass {
public int id;
public String path;
#Override
public String toString() { //include this in your model and return what you need in your drop down
return path;
}
}

Related

SimpleCursorAdaptor not showing results in my ListView in Android

I am having an issue with a "SimpleCursorAdapter" that is supposed to show a row for all results in the database. I also have an "editText" field that is supposed to be used for filtering the results set.
The issue is that the default view of the listView is to show no values and an empty table. Once I start typing in the EditText then it will filter just fine.
Is it possible to have the "default" view (when nothing is entered in the EditText) to show all values? How would I do that?
Thank you in advance and below is my code:
private void setupListView(ListView bandListView) {
ListView listView = (ListView) bandListView.findViewById(R.id.BandSelectorListView);
//Get my SQLite Helper Class
final LiveMusicSqlLiteHelper lmslh = new LiveMusicSqlLiteHelper(context);
Cursor cursor = lmslh.getBandInfo();
// The desired columns to be bound
String[] columns = new String[] {
LiveMusicArchiveConstants.bandAttributeName
};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.bandNameTextBoxId,
};
#SuppressWarnings("deprecation")
final SimpleCursorAdapter bandListAdapter = new SimpleCursorAdapter(context, R.layout.band_item_layout, cursor, columns,to);
// Assign adapter to ListView
listView.setAdapter(bandListAdapter);
//Set the click item handler
listView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(context,
"Item in position " + position + " clicked",
Toast.LENGTH_LONG).show();
}});
bandListAdapter.setFilterQueryProvider(new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
String partialValue = constraint.toString();
return lmslh.getAllSuggestedValues(partialValue);
}
});
//Create the TextWatcher. This is used to monitor the edit text so that it can filter as typing
TextWatcher filterTextWatcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
}
public void onTextChanged(CharSequence s, int start, int before,int count) {
bandListAdapter.getFilter().filter(s);
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
};
//Set the filter
EditText filterEditText = (EditText)fragmentView.findViewById(R.id.bandFilterEditText);
filterEditText.setVisibility(View.VISIBLE);
filterEditText.addTextChangedListener(filterTextWatcher);
//Close the cursor
cursor.close();
}
Does lmslh.getAllSuggestedValues(partialValue) returning all values when partialValue is null or empty?
Note the contract in the docs for FilterQueryProvider.runQuery:
Contract: when constraint is null or empty, the original results,
prior to any filtering, must be returned.
Ok, so yeah kind of stooopid....
I got a bit too zealous on my cursor.close() at the end of the method. This meant that the first load was actually empty. When I ran the query again then another cursor was created.
I moved the cursor.onClose() in the onDestroy() method and let the app control it from there.
Thanks,
Craig

Searching a ListView which uses SimpleAdapter android

I am trying to make a searchable list using a search widget I already have (android:id="#+id/searchView1"), and so far I have only found help for ListViews with ArrayAdapters and the solutions for those have not worked
Here is my code
public class SearchActivity extends Activity {
ListView listView ;
// Array of words: source http://www.knittinghelp.com/videos/knitting-glossary
String[] words = new String[] {
"( )",
"[ ]",
"*",
"**",
"alt",
"approx",
"beg",
"bet",
"BO",
"CA",
"CB",
"CC",
"cdd",
"ch",
"cm",
"cn",
"CO",
"cont"
};
// Array of meanings: source http://www.knittinghelp.com/videos/knitting-glossary
String[] meaning = new String[]{
"work instruction between parentheses, in the place directed",
"work instructions between brackets, as many times as directed",
"repeat instructions following the single asterisk as directed",
"repeat instructions between asterisks, as directed",
"alternative",
"approximately",
"beginning",
"between",
"Bind off",
"colour A",
"colour B",
"colour C",
"centered double decrease. sl2 tog, K1, pass the slipped stitches over (together)",
"chain (using crochet hook). Start with a slip knot.",
"centimeter(s)",
"cable needle: short knitting needle, used as an aid in the twisting of a cable.",
"cast on",
"continue"
};
/**
* When the search activity begins, show the view as in the search xml, and list the
* given values in the list view
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
final List<HashMap<String, String>> wordList = new ArrayList<HashMap<String, String>>();
for(int i=0; i<words.length; i++){
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put("word", words[i]);
hashMap.put("meaning", meaning[i]);
wordList.add(hashMap);
}
final SimpleAdapter adapter = new SimpleAdapter(this, wordList,
android.R.layout.simple_list_item_2,
new String[] {"word", "meaning"},
new int[] {android.R.id.text1, android.R.id.text2});
ListView listView = (ListView) findViewById(R.id.listView1);
listView.setAdapter(adapter);
EditText search = (EditText) findViewById(R.id.searchView1);
search.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
SearchActivity.this.adapter.getFilter().filter(s);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
}
}
In onTextChanged, I get an error on adapter saying it can't be resolved.
It would be awesome if someone could point me in the right direction :)
You need to add an instance variable called adapter in the outer class. Based on the code block you posted you need to have a SimpleAdapter member variable called adapter like so:
public class SearchActivity extends Activity {
ListView listView;
SimpleAdapter adapter; // this is what you're missing
because SearchActivity.this.adapter.getFilter().filter(s), is referencing an instance variable called adapter of the SearchActivity class (which currently doesn't exist).

Android, refresh listview after click on list item

I have one small problem, after i click on list item, checkbox on item dont change state. Update works perfectly, setChecked maybe, but change will appear after exiting and re-running activity. I read lot of about notifyDataSetChange(), it may work, but not. How can i fix it, like after click on item chechbox value will change.
public class SviatokPridajActivity extends Activity
{
private DatabaseOp mDbHelper;
ListView listview;
String username;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sviatok_pridaj);
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
listview = (ListView) findViewById(R.id.listSviatok);
showUserSettings();
mDbHelper = new DatabaseOp(this);
mDbHelper.open();
Cursor sviatokCursor = mDbHelper.fetchAllSviatokNastav(username, 3);
if (sviatokCursor.getCount()==0)
{
mDbHelper.naplnSviatky(username);
sviatokCursor = mDbHelper.fetchAllSviatokNastav(username, 3);
}
final SviatokCursorAdapter adapter = new SviatokCursorAdapter(this, sviatokCursor);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int stlpec, long arg3)
{
// TODO Auto-generated method stub
Cursor cur = (Cursor) adapter.getItem(stlpec);
String odosli = cur.getString(cur.getColumnIndex("_id"));
String zobraz = cur.getString(cur.getColumnIndex("dlzka"));
CheckBox check = (CheckBox)findViewById(R.id.checkBox);
if (Integer.parseInt(zobraz)==0)
{
mDbHelper.updateSviatok(odosli, username, 1);
} else {
mDbHelper.updateSviatok(odosli, username, 0);
}
check.setChecked(!check.isChecked());
adapter.notifyDataSetChanged();
}
});
}
#Override
public void onPause()
{
super.onPause();
mDbHelper.close();
}
private void showUserSettings()
{
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
username = sharedPrefs.getString("prefUsername", "NULL");
}
}
you have checked your CheckBox in itemclick but it's not reflected to your itemList so before calling adapter.notifyDataSetChanged(); you should have to refresh listItems with new changes.
I ve answered this question in this : https://stackoverflow.com/a/22954806/1332870
can you check it? if it does not solve your problem please let me know
Reload your Cursor and instead of adapter.notifyDataSetChanged(); use adapter.changeCursor(reloadedCursor);
Not sure if this is a strain on the main thread but you could just set the adapter again in the on click method.

Getting current suggestion from `AutoCompleteTextView`

How do you get the current top suggestion in an AutoCompleteTextView? I have it suggesting items, and I have a text change listener registered. I also have a list on the same screen. As they type, I want to scroll the list to the current "best" suggestion. But I can't figure out how to access the current suggestions, or at least the top suggestion. I guess I'm looking for something like AutoCompleteTextView.getCurrentSuggestions():
autoCompleteTextView.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
String currentText = autoCompleteTextView.getText();
String bestGuess = autoCompleteTextView.getCurrentSuggestions()[0];
// ^^^ mewthod doesn't exist
doSomethingWithGuess(bestGuess);
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// do nothing
}
public void afterTextChanged(Editable s) {
// do nothing
}
});
I've done what you want to do with the following code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.autocomplete_1);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, COUNTRIES);
AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit);
textView.setAdapter(adapter);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
Log.d(TAG, "dataset changed");
Object item = adapter.getItem(0);
Log.d(TAG, "item.toString "+ item.toString());
}
});
}
item.toString will print the text that is displayed on the first item.
Note that this will happen even if you aren't showing the pop-up (suggestions) yet. Also, you should check if there are any items that passed the filter criteria (aka the user's input).
To solve the first problem:
int dropDownAnchor = textView.getDropDownAnchor();
if(dropDownAnchor==0) {
Log.d(TAG, "drop down id = 0"); // popup is not displayed
return;
}
//do stuff
To solve the second problem, use getCount > 0
AutoCompleteTextView does not scroll down to the best selection, but narrows down the selection as you type. Here is an example of it: http://developer.android.com/resources/tutorials/views/hello-autocomplete.html
As I see it from AutoCompleteTextView there is no way to get current list of suggestions.
The only way seem to be writing custom version of ArrayAdapter and pass it to AutoCompleteTextView.setAdapter(..). Here is the source to ArrayAdapter. You must only change a method in inner class ArrayFilter.performFiltering() so that it exposes FilterResults:
.. add field to inner class ArrayFilter:
public ArrayList<T> lastResults; //add this line
.. before end of method performFiltering:
lastResults = (ArrayList<T>) results; // add this line
return results;
}
Using it like this (adapted example from link):
AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autocomplete_country);
CustomArrayAdapter<String> adapter = new CustomArrayAdapter<String>(this, R.layout.list_item, COUNTRIES);
textView.setAdapter(adapter);
// read suggestions
ArrayList<String> suggestions = adapter.getFilter().lastResult;

Android, add() function of ArrayAdapter not working

I have an ArrayAdapter (myAdapter) attached to an AutoCompleteTextView (textView) component.
Once the user presses a character I would like to populate AutoCompleteTextView's drop down list with items containing this character.
I retrieve the items using AsyncTask (which uses a web service).
I call myAdapter.add(item) but the drop down list is empty.
I added a call myAdapter.getCount() after each addition and it shows zero every time.
Calling notifyDataSetChanged() didn't help.
I even tried to add simple String objects instead of my custom objects, to no avail.
What am I doing wrong?
Edit: I changed the code as miette suggested below but still to no avail.
Generally, what I do is after text is changed in my auto complete text view, I call a new AsyncTask and pass it the entered text and a Handler (see afterTextChanged()). The task retrieves objects relevant to the text and once done the Handler's handleMessage() is called. In handleMessage() I attempt to populate the adapter's objects. But still the adapter's drop down list ends up empty.
Here is my code:
public class AddStockView extends Activity
implements OnClickListener, OnItemClickListener, TextWatcher {
ArrayAdapter<Stock> adapter;
AutoCompleteTextView textView;
Vector<Stock> stocks;
public AddStockView() {
// TODO Auto-generated constructor stub
stocks = new Vector<Stock>();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.add_stock_view);
findViewById(R.id.abort_button).setOnClickListener(this);
adapter = new ArrayAdapter<Stock>(this,
android.R.layout.simple_dropdown_item_1line, stocks);
//adapter.setNotifyOnChange(true);
textView = (AutoCompleteTextView)
findViewById(R.id.search_edit_text);
textView.setAdapter(adapter);
textView.setOnItemClickListener(this);
textView.addTextChangedListener(this);
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId())
{
case R.id.abort_button:
finish();
break;
case R.id.search_edit_text:
break;
}
}
#Override
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
// TODO Auto-generated method stub
Stock stockToAdd = (Stock)parent.getAdapter().getItem(position);
//TODO: Add the above stock to user's stocks and close this screen
finish();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.layout.menu, menu);
CategoryMenu.getInstance().populateMenu(menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
CategoryMenu.getInstance().menuItemSelected(item, this);
return false;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
return true;
}
#Override
public void afterTextChanged(Editable text) {
// TODO Auto-generated method stub
if (text.toString().equals(""))
return;
new AppTask().execute(new AppTask.Payload(Consts.taskType.SEARCH_STOCK,
new Object[] {text, handler}, this));
}
#Override
public void beforeTextChanged(CharSequence a0, int a1, int a2, int a3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence a0, int a1, int a2, int a3) {
// TODO Auto-generated method stub
}
private void addStockItemsToAdapter(Vector<Object> dataItems)
{
for (int i = 0; i <dataItems.size(); i++)
{
Stock stk = (Stock)dataItems.elementAt(i);
stocks.add(stk);
}
}
public void populateAdapter()
{
addStockItemsToAdapter(ContentReader.getInstance.getDataItems());
adapter.notifyDataSetChanged();
int size = adapter.getCount(); // size == 0 STILL!!!!
textView.showDropDown();
}
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
populateAdapter();
}
};
}
Thanks a lot, Rob
I had the exact same problem. After examining the ArrayAdapter and AutoCompleteTextView source code, I found out that the problem was, in short, that:
the original object list is stored in ArrayAdapter.mObjects.
However, AutoCompleteTextView enables ArrayAdapter's filtering, meaning that new objects are added to ArrayAdapter.mOriginalValues, while mObjects contains the filtered objects.
ArrayAdapter.getCount() always returns the size of mObjects.
My solution was to override ArrayAdapter.getFilter() to return a non-filtering filter. This way mOriginalValues is null and mObjects is used instead in all cases.
Sample code:
public class MyAdapter extends ArrayAdapter<String> {
NoFilter noFilter;
/*
...
*/
/**
* Override ArrayAdapter.getFilter() to return our own filtering.
*/
public Filter getFilter() {
if (noFilter == null) {
noFilter = new NoFilter();
}
return noFilter;
}
/**
* Class which does not perform any filtering.
* Filtering is already done by the web service when asking for the list,
* so there is no need to do any more as well.
* This way, ArrayAdapter.mOriginalValues is not used when calling e.g.
* ArrayAdapter.add(), but instead ArrayAdapter.mObjects is updated directly
* and methods like getCount() return the expected result.
*/
private class NoFilter extends Filter {
protected FilterResults performFiltering(CharSequence prefix) {
return new FilterResults();
}
protected void publishResults(CharSequence constraint,
FilterResults results) {
// Do nothing
}
}
}
Create an array adapter with a vector or array like:
ArrayAdapter(Context context, int textViewResourceId, T[] objects)
By initializing your arrayadapter, you will make it listen to objects array. Do not add item to the adapter or clear the adapter, do your additions in "objects" array and also clear it. After changes on this array call
adapter.notifyDataSetChanged();
More specifically
ArrayAdapter<YourContentType> yourAdapter = new ArrayAdapter<YourContentType> (this,R.id.OneOfYourTextViews,YourDataList);
yourAdapter.notifyDataSetChanged();
aTextView.setText(yourAdapter.isEmpty() ? "List is empty" : "I have too many objects:)");
This should be done after loading YourDataList, I checked your code, are you sure handler calls addStockItemsToAdapter() before you look your adapter is empty or not?
You should also check if stocks vector has any elements in it.
Where do you call addItemsToAdapter()?
Can you show us, how you have tried to add simple Strings to your Adapter?
Edit: out of the comments the helpful code sample:
adapter = new ArrayAdapter<Stock>(this, android.R.layout.simple_dropdown_item_1line, stocks);
adapter.notifyDataSetChanged();
textView.setAdapter(adapter);

Categories

Resources