问题
I have been working on AutoCompleteTextView
. I was able to get the suggestion and all in the drop down list as we type.

My question is: Can we highlight the typed character in the suggestion drop down list?
回答1:
I have achieved the functionality. The solution is as follows:
AutoCompleteAdapter.java
public class AutoCompleteAdapter extends ArrayAdapter<String> implements
Filterable {
private ArrayList<String> fullList;
private ArrayList<String> mOriginalValues;
private ArrayFilter mFilter;
LayoutInflater inflater;
String text = "";
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);
inflater = LayoutInflater.from(context);
}
@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) {
View view = convertView;
// tvViewResourceId = (TextView) view.findViewById(android.R.id.text1);
String item = getItem(position);
Log.d("item", "" + item);
if (convertView == null) {
convertView = view = inflater.inflate(
android.R.layout.simple_dropdown_item_1line, null);
}
// Lookup view for data population
TextView myTv = (TextView) convertView.findViewById(android.R.id.text1);
myTv.setText(highlight(text, item));
return view;
}
@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 (prefix != null) {
text = prefix.toString();
}
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();
}
}
}
public static CharSequence highlight(String search, String originalText) {
// ignore case and accents
// the same thing should have been done for the search text
String normalizedText = Normalizer
.normalize(originalText, Normalizer.Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
.toLowerCase(Locale.ENGLISH);
int start = normalizedText.indexOf(search.toLowerCase(Locale.ENGLISH));
if (start < 0) {
// not found, nothing to to
return originalText;
} else {
// highlight each appearance in the original text
// while searching in normalized text
Spannable highlighted = new SpannableString(originalText);
while (start >= 0) {
int spanStart = Math.min(start, originalText.length());
int spanEnd = Math.min(start + search.length(),
originalText.length());
highlighted.setSpan(new ForegroundColorSpan(Color.BLUE),
spanStart, spanEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
start = normalizedText.indexOf(search, spanEnd);
}
return highlighted;
}
}
}
MainActivity.java
public class MainActivity extends Activity {
String[] languages = { "C", "C++", "Java", "C#", "PHP", "JavaScript",
"jQuery", "AJAX", "JSON" };
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List<String> wordList = new ArrayList<String>();
Collections.addAll(wordList, languages);
AutoCompleteAdapter adapter = new AutoCompleteAdapter(this,
android.R.layout.simple_dropdown_item_1line,
android.R.id.text1,wordList);
AutoCompleteTextView acTextView = (AutoCompleteTextView) findViewById(R.id.languages);
acTextView.setThreshold(1);
acTextView.setAdapter(adapter);
}
}
Working like charm!
Enjoy!
回答2:
I reckon that should be possible, provided you know the index/indices of the character(s) the user typed last. You can then use a SpannableStringBuilder
and set a ForegroundColorSpan
and BackgroundColorSpan
to give the character(s) the appearance of a highlight.
The idea looks somewhat like this:
// start & end of the highlight
int start = ...;
int end = ...;
SpannableStringBuilder builder = new SpannableStringBuilder(suggestionText);
// set foreground color (text color) - optional, you may not want to change the text color too
builder.setSpan(new ForegroundColorSpan(Color.RED), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// set background color
builder.setSpan(new BackgroundColorSpan(Color.YELLOW), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// set result to AutoCompleteTextView
autocompleteTextview.setText(builder);
Note that the 'highlight' will remain as long as you don't type another character. You may want to remove the highlight when e.g. the user changes the cursor position in the AutoCompleteTextView
, but I'll leave that up to you.
回答3:
I know it's to late for answering this question , But as I personally battled to find the answer , finally I wrote it myself (with the help of the answer from @MH. ofcourse), so here it is :
First , You have to create a Custom ArrayAdapter :
public class AdapterAustocomplete extends ArrayAdapter<String> {
private static final String TAG = "AdapterAustocomplete";
String q = "";
public AdapterAustocomplete(Context context, int resource, List objects) {
super(context, resource, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
String item = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView =
// I'll use a custom view for each Item , this way I can customize it also!
G.inflater.from(getContext()).inflate(R.layout.textview_autocomplete, parent, false);
}
// Lookup view for data population
TextView myTv = (TextView) convertView.findViewById(R.id.txt_autocomplete);
int start = item.indexOf(q);
int end = q.length()+start;
SpannableStringBuilder builder = new SpannableStringBuilder(item);
builder.setSpan(new ForegroundColorSpan(Color.RED), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
myTv.setText(builder);
return convertView;
}
public void setQ(String q) {
this.q = q;
}
}
And in the Code that you want to set the adapter for AutoCompleteTextView ;
AutoCompleteTextView myAutoComplete = findViewById(its_id);
AdapterAustocomplete adapter_autoComplete = new AdapterAustocomplete(getActivity(), 0, items); // items is an arrayList of Strings
adapter_autoComplete.setQ(q);
myAutoComplete.setAdapter(adapter_autoComplete);
来源:https://stackoverflow.com/questions/15119113/autocomplete-textbox-highlighting-the-typed-character-in-the-suggestion-list