I'm on an android project since September, and I've to deal with AutocompleteTextView.
I made my personnal ArrayAdapter to populate the dropdown suggestion list, it works, but act strangely.
When i select an item in the dropdown list, it replace the text in my textView by the selection (that's okay), but after this, reShow the Dropdown.
I want it to hide until the user type something else on the keyboard.
Here is a sample of my code :
private List<String> autocompleteAddress;
addressBox = (AutoCompleteTextView)findViewById(R.id.form_address_box);
autocompleteAdapterAddress = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, autocompleteAddress){
#Override
public Filter getFilter(){
Filter custom_filter = new Filter(){
#Override
protected FilterResults performFiltering(CharSequence constraint){
FilterResults filterResults = new FilterResults();
filterResults.values = autocompleteAddress;
filterResults.count = autocompleteAddress.size();
return filterResults;
}
#Override
protected void publishResults(CharSequence contraint, FilterResults results){
notifyDataSetChanged();
}
};
return custom_filter;
}
};
addressBox.setAdapter(autocompleteAdapterAddress);
addressBox.addTextChangedListener(new TextWatcher(){
#Override
public void onTextChanged(CharSequence s, int start, int before, int count){
//ac is an asynctask populating the suggestion list (autocompleteAddress)
GetGoogleAutocompletion ac = new GetGoogleAutocompletion();
ac.execute(addressBox.getText().toString());
}
#Override public void afterTextChanged(Editable s){}
#Override public void beforeTextChanged(CharSequence s, int start, int count, int after){}
});
addressBox.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// here i just store the autocompleted text in a String
}
});
I thought the setText() method would be call in onItemClick(), and I could have used dismissDropDown(), but as i overrided onItemClick(), I'm pretty sure it's not there.
So i really don't know neither where the setText() is called, nor how to avoid the display of the dropDown menu after a selection.
Thanks in advance!
Related
I have an AutoCompleteTextView, and depending from the changes in it, it shows the dropdown list with the data from server. Via listener after changing every symbol I make request to the server and take some list.
After that I show that list in AutoCompleteTextView, in code I do it by this way:
List<String> list = new ArrayList<String>();
for (int i = 0; i < jsonArray.length(); i++) {
list.add(jsonArray.getJSONObject(i).getString("title"));
}
String[] cities = list.toArray(new String[list.size()]);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(DistanceCalculation.this, R.layout.support_simple_spinner_dropdown_item, cities);
AutoCompleteTextView my = (AutoCompleteTextView) myView;
my.setAdapter(adapter);
Problem is it oftenly shows only the first element of the list, and after long click it shows the full list. I don understand why its happening.
Sorry for the bad eng, thanks in advance! Also you could check the rest of the code below:
xml part:
<AutoCompleteTextView
android:id="#+id/from"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="15dp"
android:background="#drawable/td_inp"
android:hint="Откуда"
android:paddingBottom="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="5dp"
android:textColor="#000"
android:textColorHint="#757575" />
AutoCompleteTextView and its listener in onCreate
tCityFrom = (AutoCompleteTextView) findViewById(R.id.from);
tCityFrom.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
if(s.length() >= 2) load_city(ssid, s.toString(),tCityFrom);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
I assume you want to show AutoComplete suggestions according to what user types. You have to load data from server onTextChanged():
tCityFrom = (AutoCompleteTextView) findViewById(R.id.from);
tCityFrom.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) { }
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s.length() >= 2)
load_city(ssid, s.toString(),tCityFrom);
}
});
Then declare ArrayList and Adapter globally:
List<String> list;
ArrayAdapter<String> adapter;
In onCreate():
list = new ArrayList<String>();
adapter = new ArrayAdapter<String>(DistanceCalculation.this, R.layout.support_simple_spinner_dropdown_item, cities);
AutoCompleteTextView my = (AutoCompleteTextView) myView;
my.setAdapter(adapter);
Replace your first code snippet of load_city() with below code :
list.clear();
for (int i = 0; i < jsonArray.length(); i++) {
list.add(jsonArray.getJSONObject(i).getString("title"));
}
adapter.notifyDataSetChanged();
Hope this helps.
I have a ListView populated by a String array. The user searches through edittext and it filters from the list, but when I click on one of the list items after filtering, the selected item is not returned but something else entirely. This was why it was going wrong:
Filter code:
et.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence cs, int start, int before, int count) {
adapter.getFilter().filter(cs);
}
#Override
public void afterTextChanged(Editable s) {
}
List item click code:
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String s = array[position];
intent.putExtra(s);
setResult(RESULT_OK, intent);
finish();
}
});
Then I would read the string through OnActivityResult. The problem is that when the list is filtered, the list items are reduced. On selecting one of the items returns the position number of the reduced list, not the array. That's why the returned string is actually the string according to the array not according to the reduced list. How can I overcome this ?
problem is simple when you filtered the list and click on item you won't get the filtered item clicked because in lv.setOnItemClickListener(new OnItemClickListener() {...} you are passing position of original list not the filtered list.
Workaround is instead of getting from main list try getting it like this :
String a = array[parent.getItemAtPosition(position)];
or
String a = array[adapter.getItem(position)];
or
String a = array[(String) parent.getAdapter().getItem(position)];
I have a ListView with names of people and an ActionBar with a Search widget.
What I want to do is focus the first item in the ListView that contains the search query as a substring.
For example if I have a person named "John Doe" and i search for "hn D" that row should be focused as long as it is the first one that contains "hn D" as a substring.
Note that I don't want the items that don't contain the substring removed from the list.
This is how I made the list.
activity_main.xml
<ListView android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
list_item.xml
<TextView
android:id="#+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dip"
android:textSize="16sp"
android:textStyle="bold" />
MainActivity.java
String[] names = {"John Doe","Mark Marky","Donald Duck","Derp Derpson"};
lv = (ListView) findViewById(R.id.list_view);
adapter = new ArrayAdapter<String>(this,R.layout.list_item, R.id.name, names);
lv.setAdapter(adapter);
I also have an action bar with the search widget and i implemented the onQueryTextChange() and onQueryTextSubmit() methods.
The question is how do I search through the list in those methods and how do I focus the appropriate list item?
To do textual search you can use a filter in your adapter
public class Adapter extends BaseAdapter implements Filterable {
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//do you work
notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
List<Object> searchedList = new ArrayList<Object>();
results.count = searchedList.size();
results.values = searchedList;
return results;
}
};
return filter;
}
}
and use it like that :
private void searchAction(String query) {
youradapter.getFilter().filter(_query);
}
searchedittext.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
YourActivity.this.youradapter.getFilter().filter(cs);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
More than one person have had the problem of how to implement a Filter for a ListView that uses a SimpleCursorAdapter. I had this problem and I have found lots of answers about this in this web. I have taken pieces of code from everywhere until I finally got it work and it was simpler that it looked like.
I've seen the Google I/O 2010 - The world of ListView video on youtube and it says that you have to implement getFilter method and implements Filterable on your class adapter, something like this:
public class MyListCursorAdapter extends SimpleCursorAdapter implements Filterable{
...
#Override
public Filter getFilter() {
return new Filter(){
#Override
protected FilterResults performFiltering(CharSequence charSequence){
FilterResults results = new FilterResults();
//If there's nothing to filter on, return the original data for your list
if(charSequence == null || charSequence.length() == 0){
results.values = originalData;
results.count = originalData.getCount();
}
else{
Cursor filterResultsData = null;
filterResultsData = DB.getResults(charSequence);
results.values = filterResultsData;
results.count = filterResultsData.getCount();
}
return results;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults){
filteredData = (Cursor) filterResults.values;
if (filterResults.count > 0) {
notifyDataSetChanged();
}else{
notifyDataSetInvalidated();
}
}
};
}
}
At least is what I tried to do. I've seen that using ArrayAdapter instead of Cursor, works pretty well. But in the case of Cursor it didn't work, at least not for me. Maybe I'm doing something wrong. So I was a little confused about what do to. I know that I have a edit text, a list view and everytime a put some text on my edit text I want my list get filtered.
Now I'm going to answer my own question since I want to share with you my solution.
This is What I have done:
Layout:
<EditText
android:id="#+id/editTextSearch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:hint="#string/search" >
</EditText>
<ListView
android:id="#id/android:list"
android:textFilterEnabled="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
Pay attention to android:textFilterEnabled="true" in ListView.
My ListActivity or ListFragment:
public class ClientesActivity extends ListFragment {
private MyListCursorAdapter myAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_clientes, container, false);
//call to a method that fill my list
myListGetFilled(view);
//Put a listener to edit text search
EditText etSearch = (EditText) view.findViewById(R.id.editTextSearch);
etSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
myAdapter.getFilter().filter(cs);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
return view;
}
private void myListGetFilled(View view){
Cursor mCursor = DB.fillMyList(getActivity());
if(mCursor.getCount()>0){
String[] from = new String[] { "name", "description"};
int[] to = new int[] { R.id.textViewName, R.id.textViewDescription};
ListView myListView = (ListView) view.findViewById (android.R.id.list);
myAdapter = new MyListCursorAdapter(context, R.layout.activity_row_list, mCursor, from, to);
myListView .setAdapter(myAdapter);
}
}
And finally my custom cursor adapter:
public class MyListCursorAdapter extends SimpleCursorAdapter implements Filterable{
...
/*THE METHOD THAT DOES THE MAGIC*/
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
if (getFilterQueryProvider() != null){
return getFilterQueryProvider().runQuery(constraint);
}
Cursor filterResultsData = DB.getResults(constraint);
return filterResultsData;
}
}
And that's it!!.
Hope this can be useful to anyone. And if you think there is a better solution than this one, please share!!.
I implemented multiple row list view(4 rows in single item).i want to search only based on second row in my list view.i implemented search functionality using text watcher that is not working properly. please help me guys.Thanks in advance.
inputsearch = (EditText) findViewById(R.id.inputsearch);
lst = (ListView) findViewById(android.R.id.list);
lst.setBackgroundColor(Color.WHITE);
lst.setCacheColorHint(Color.WHITE);
SimpleAdapter adapter = new SimpleAdapter(this, mylistData,R.layout.simple_list_item2, row, new int[] { R.id.tv1,
R.id.tv2, R.id.tv3, R.id.tv4, R.id.tv5 });
lst.setAdapter(adapter);
inputsearch.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence cs, int start, int before,
int count) {
// String array_sort[]=new String[headlines.length];
adapter.getFilter().filter(cs);
}
public void afterTextChanged(Editable arg0) {
}
public void beforeTextChanged(CharSequence cs, int start,
int before, int count) {
}
});