Getting current suggestion from `AutoCompleteTextView` - android

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;

Related

ArrayList getting changed without any operation on it

I am trying to write a login in Android. The Logic is I am initiating an ArrayList in a constructor of a PopupWindow. In that PopupWindow I am showing a list using RecyclerView, by passing this ArrayList into the constructor of the Adapter Class. In that list I am using an EditText to search the list using addTextChangedListener.
The code is as follows,
MainActivity.Java
ArrayList<CompanyModel> companyList , backupCompanyList;
CompanyAdapter companyAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
//initialisation of both arraylists
companyList = getCompanylist();
backupCompanyList = companyList;
}
// inner class declared in the MainActivity.java
public class ShowCompanyData{
public ShowCompanyData(){
//initialise popupwindow
//get view of recyclerview and other view components of the popupwindow , and setadapter to the recyclerview
companyAdapter = new CompanyAdapter(context , companyList );
et_search.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
String text = et_search.getText().toString().toLowerCase(Locale.getDefault());
companyAdapter.filter(text);
}
});
}
}
//this button belongs to the Layout file of MainActivity.
public void showPopupList(View v){
// this is a button click where i am showing the company list popupwindow
companyListPopupWindow.showAtLocation(layout, Gravity.CENTER, 0, 0);
}
CompanyAdapter.java
public class CompanyAdapter extends RecyclerView.Adapter<CompanyAdapter.ViewHolder> {
Context context;
ArrayList<CompanyModel> mainArrayList;
ArrayList<CompanyModel> list;
// other imp methods are also written , but not shown because not necessary to show here
public CompanyAdapter(Context context, ArrayList<CompanyModel> mainArrayList) {
this.context = context;
this.mainArrayList = mainArrayList;
this.list = new ArrayList<>();
this.list.addAll(mainArrayList);
}
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
mainArrayList.clear();
if (charText.length() == 0) {
mainArrayList.addAll(list);
} else {
for (CompanyModel wp : list) {
if (wp.getCompanyName().toLowerCase(Locale.getDefault()).contains(charText)) {
mainArrayList.add(wp);
}
}
}
notifyDataSetChanged();
}
}
Here the issue I am facing is, when I search something in in the EditText of PopupWindow where the list of Company's is shown, the ArrayList backupCompanyList is getting modified same as the companyList ArrayList.
My question is, I am not assigning anything to the backupCompanyList, also not passing it as a parameter to the Adapter Class, still when I debug the app the backupCompanyList are showing same contents as companyList, after searching anything in the EditText.
Where the backupCompanyList should contains the data (unchanged) assigned in OnCreate and should not modify the changes, because there are no operations or assignments done to the backupCompanyList in the entire program.
Can anyone guide me to overcome this issue.
Note :
I have not written full code, I have written only necessary code
Both ArrayLists (companyList & backupCompanyList) are showing proper data before entering any text into EditText of search. And issue is occuring only after searching.
In your Activity's onCreate method, your are assigning companyList reference to backupCompanyList reference. Both companyList and backupCompanyList are referring to the same ArrayList object reference returned from getCompanyList() method. That's why, it's reflecting both lists are changing together. In actual, there's only one ArrayList object.
Instead of:
companyList = getCompanyList();
backupCompanyList = companyList;
Use
companyList = getCompanyList();
backupCompanyList = new ArrayList<>(companyList);

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

How to implement searchFilter in ListView having Alphabet-indexed Section Headers

I have to implement Filter in ListView having Alphabetical SectionHeader .ListView having Alphabetic Section Header
I used the example from above link to create my ListView. How to implement Search Filter in this ListView. I need a Layout like the below
For this to implement you need a TextWatcher for the edittext in which user will type when user will type something you create a Arraylist that will be updated with the items and then notify the Listview
search.addTextChangedListener(new TextWatcher() {
Boolean called =false;
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
coffeeshopsearch=new ArrayList<CoffeeShopBean>();
for (int i = 0; i < coffeeShop.size(); i++) {
if(coffeeShop.get(i).name1.toLowerCase().contains(String.valueOf(s).toLowerCase()))
{
coffeeshopsearch.add(coffeeShop.get(i));
}
}
if(coffeeshopsearch.size()>0)
{
lv.setVisibility(View.VISIBLE);
adapter.add(coffeeshopsearch);
adapter.notifyDataSetChanged();
}
else
{
if(!called)
{
Toast.makeText(getActivity(), "No Items Found!!!!", Toast.LENGTH_SHORT).show();
called=true;
}
lv.setVisibility(View.GONE);
}
}

.setText not working properly

So I'm in a basic part of my application I'm wanting to make. I've never gotten this error before, and I don't know what's going on. My .setText is throwing an error saying "setText cannot be resolved or is not a field" I've looked around and haven't been able to find my problem. I believe I'm doing it correctly. If anyone could help me out that'd be great!
MainActivity.java:
public class MainActivity extends Activity {
final TextView loading_Text = (TextView)findViewById(R.id.textView4);
final EditText name_Edit = (EditText)findViewById(R.id.editText1);
//String Values
String Age="";
String Name = name_Edit.getText().toString();
//Int Values
int Gender = 0; //1 male | 2 female
int Group = 0; //Different groups for ages and genders
int save_Info = 0; //save info to phone
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button male_Button= (Button)findViewById(R.id.button1);
Button female_Button = (Button)findViewById(R.id.button2);
male_Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Gender++;//Adds one to show this user is a male.
loading_Text.setText=(Name);
}
});
}
I saw two problems:
First:
loading_Text.setText=(Name);
Should be
loading_Text.setText("The text you want to set");
You'll need to take a look at the API document to see how to call the method.
Second:
Move these part:
final TextView loading_Text = (TextView)findViewById(R.id.textView4);
final EditText name_Edit = (EditText)findViewById(R.id.editText1);
//String Values
String Age="";
String Name = name_Edit.getText().toString();
inside your onCreate, like this:
public class MainActivity extends Activity {
TextView loading_Text;
EditText name_Edit;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loading_Text = (TextView)findViewById(R.id.textView4);
name_Edit = (EditText)findViewById(R.id.editText1);
Or you'll get NullPointerException.
This is because you were trying to reach the View's property before the view is being initialized. View will be initialized after setContentView, and what you were intend to do was findViewById from R.layout.activity_main before it had been loaded.
Similarly, you'll need to move this call of method:
String Name = name_Edit.getText().toString();
somewhere after setContentView.
setText is a function. So you would need to pass name as a argument.
like loading_Text.setText(Name);
Change
loading_Text.setText=(Name);
to this:
loading_Text.setText(Name);
Also, if you don't see anything in the textview, it is because you are getting the edittext's text before you even create your views, I use an on edittext listener like this to refresh the String when the edit text is changed:
name_Edit.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
Name = name_Edit.getText().toString();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
I hope this works for you :)

AutoCompleteTextView not showing any drop down items

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;
}
}

Categories

Resources