Reputation: 2505
I am working on an application in which I am using AutoCompleteTextView and am facing few issues. Please find the details of the issues below.
The following values are present in the data:
1) Manish Logan Jain
2) M. J. (Logan Fern)
3) Logan
Issues:
1) When user searches for Manish, Manish Logan Jain is shown as a suggestion. But when user enters Logan Jain, then no results are returned.
2) When user enters Logan, I expect second value to be shown as suggestion, but currently, the suggestion lists shows nothing.
3) When user enters ogan, I expect suggestion 3 to be shown. Currently, its not shown.
AutoCompleteView xml:
AutoCompleteTextView
android:id="@+id/autoCompleteTextView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:ems="10"
android:hint="@string/enter_user_name" >
<requestFocus />
</AutoCompleteTextView>
Java code that populates the data:
List<String> namesList = new ArrayList<String>(stops);
namesList.add("Manish Logan Jain");
namesList.add("Logan");
namesList.add("M. J. (Logan Fern)");
ArrayAdapter<String> namesSuggestion = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, namesList);
AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
textView.setAdapter(namesSuggestion);
textView.setThreshold(1);
Has someone faced similar issues? And if yes, then what are the possible solutions for this?
Upvotes: 0
Views: 564
Reputation: 24720
use a CursorAdapter for your ACTV and call setFilterQueryProvider(FilterQueryProvider) for custom filtering (use a MatrixCursor for filtered data)
EDIT: sample FilterQueryProvider
class FQP extends LinkedList<String> implements FilterQueryProvider {
@Override
public Cursor runQuery(CharSequence constraint) {
if (constraint == null) {
return null;
}
Log.d("TAG", "runQuery " + constraint);
String lowerConstraint = constraint.toString().toLowerCase();
String[] columns = {
"_id", "name"
};
int id = 0;
MatrixCursor c = new MatrixCursor(columns);
for (String name : this) {
String lowerName = name.toLowerCase();
if (lowerName.indexOf(lowerConstraint) != -1) {
c.newRow().add(id++).add(name);
}
}
return c;
}
};
test it with the following in onCreate:
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
AutoCompleteTextView actv = new AutoCompleteTextView(this);
String[] from = {"name"};
int[] to = {android.R.id.text1};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_dropdown_item_1line, null, from, to);
FQP fqp = new FQP();
fqp.add("Manish Logan Jain");
fqp.add("Logan");
fqp.add("M. J. (Logan Fern)");
adapter.setFilterQueryProvider(fqp);
actv.setAdapter(adapter);
actv.setThreshold(1);
ll.addView(actv);
setContentView(ll);
Upvotes: 2
Reputation: 1
The default result string set is returned by treat the imput string as prefix. This is implemented in a ArrayFilter object. Code is like
/**
* <p>An array filter constrains the content of the array adapter with
* a prefix. Each item that does not start with the supplied prefix
* is removed from the list.</p>
*/
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (mLock) {
mOriginalValues = new ArrayList<T>(mObjects);
}
}
if (prefix == null || prefix.length() == 0) {
synchronized (mLock) {
ArrayList<T> list = new ArrayList<T>(mOriginalValues);
results.values = list;
results.count = list.size();
}
} else {
String prefixString = prefix.toString().toLowerCase();
final ArrayList<T> values = mOriginalValues;
final int count = values.size();
final ArrayList<T> newValues = new ArrayList<T>(count);
for (int i = 0; i < count; i++) {
final T value = values.get(i);
final String valueText = value.toString().toLowerCase();
// First match against the whole, non-splitted value
if (valueText.startsWith(prefixString)) {
newValues.add(value);
} else {
final String[] words = valueText.split(" ");
final int wordCount = words.length;
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefixString)) {
newValues.add(value);
break;
}
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
if you want change the return string to the set that contains the input string, A customed ArrayFilter is needed.
Upvotes: 0
Reputation: 23638
Try out the below code:
public class AutoCompleteAdapter extends ArrayAdapter<Address> implements Filterable {
private LayoutInflater mInflater;
private Geocoder mGeocoder;
private StringBuilder mSb = new StringBuilder();
public AutoCompleteAdapter(final Context context) {
super(context, -1);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mGeocoder = new Geocoder(context);
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final TextView tv;
if (convertView != null) {
tv = (TextView) convertView;
} else {
tv = (TextView) mInflater.inflate(android.R.layout.simple_dropdown_item_1line, parent, false);
}
tv.setText((createFormattedAddressFromAddress(getItem(position))));
return tv;
}
private String createFormattedAddressFromAddress(final Address address) {
mSb.setLength(0);
final int addressLineSize = address.getMaxAddressLineIndex();
for (int i = 0; i < addressLineSize; i++) {
mSb.append(address.getAddressLine(i));
if (i != addressLineSize - 1) {
mSb.append(", ");
}
}
return mSb.toString();
}
@Override
public Filter getFilter() {
Filter myFilter = new Filter() {
@Override
protected FilterResults performFiltering(final CharSequence constraint) {
List<Address> addressList = null;
if (constraint != null) {
try {
addressList = mGeocoder.getFromLocationName((String) constraint, 5,23.0,72.0,23.9,72.9);
} catch (IOException e) {
}
}
if (addressList == null) {
addressList = new ArrayList<Address>();
}
final FilterResults filterResults = new FilterResults();
filterResults.values = addressList;
filterResults.count = addressList.size();
return filterResults;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(final CharSequence contraint, final FilterResults results) {
clear();
for (Address address : (List<Address>) results.values) {
add(address);
}
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
@Override
public CharSequence convertResultToString(final Object resultValue) {
return resultValue == null ? "" : ((createFormattedAddressFromAddress((Address) resultValue).split(", Ahmedabad")[0].length()<6)?createFormattedAddressFromAddress((Address) resultValue).split(", Gujarat")[0]:createFormattedAddressFromAddress((Address) resultValue).split(", Ahmedabad")[0]);
}
};
return myFilter;
}
}
Upvotes: 0
Reputation: 645
What your looking for Is cannot be done directly. But i suggest you to use MultiCompleteTextView.
refer this link: http://www.c-sharpcorner.com/uploadfile/manish1231/autocomplete-and-multicomplete-textview-in-mono-for-android/
Upvotes: 0
Reputation: 56925
Use a custom Adapter which implements Filterable. In the getFilter method use String.contains() as per your requirement.
Please check this link.
Upvotes: 2