AutoCompleteTextView:继承自EditText,是可提供建议用以自动补全文本的输入框,其基本用法相信大家都很了解,本文记录一下使用过程中遇到的一些问题:
查看AutoCompleteTextView源码,我们会发现当completionThreshold<=0时,会默认修改为1:
/**
* Specifies the minimum number of characters the user has to type in the
* edit box before the drop down list is shown.
*
* When threshold
is less than or equals 0, a threshold of
* 1 is applied.
*
* @param threshold the number of characters to type before the drop down
* is shown
*
* @see #getThreshold()
*
* @attr ref android.R.styleable#AutoCompleteTextView_completionThreshold
*/
public void setThreshold(int threshold) {
if (threshold <= 0) {
threshold = 1;
}
mThreshold = threshold;
}
那么我们如果想让completionThreshold为0,在不输入任何内容时也有提示信息该怎么办呢?
继续查看源码,会发现enoughToFilter()方法:
/**
* Returns true
if the amount of text in the field meets
* or exceeds the {@link #getThreshold} requirement. You can override
* this to impose a different standard for when filtering will be
* triggered.
*/
public boolean enoughToFilter() {
if (DEBUG) Log.v(TAG, "Enough to filter: len=" + getText().length()
+ " threshold=" + mThreshold);
return getText().length() >= mThreshold;
}
其作用就是用以判断输入长度是否满足显示提示列表,那么我们只需要自定义AutoCompleteTextView重写该方法即可:
public class MyAutoCompleteTextView extends AutoCompleteTextView {
public MyAutoCompleteTextView(Context context) {
super(context);
}
public MyAutoCompleteTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean enoughToFilter() {
return true;
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
//当控件获得焦点显示提示列表
performFiltering(getText(), KeyEvent.KEYCODE_UNKNOWN);
}
}
点击空白区域以后,提示列表消失,想再显示出来怎么办?
在onClick()方法中调用showDropDown()即可:
myAutoCompleteTextView.setOnClickListener(v -> myAutoCompleteTextView.showDropDown());
查看ArrayAdapter源码,其继承自继承自BaseAdapter
并实现了Filterable
接口,通过ArrayFilter的performFiltering完成筛选:
那么我们只需要自定义Adapter,使用自己的Filter:
public class CustomAdapter extends BaseAdapter implements Filterable {
private Context mContext;
private List mObjects;
private ArrayList mOriginalValues;
private final Object mLock = new Object();
private CustomFilter mFilter;
public CustomAdapter(Context context) {
this.mContext = context;
mFilter = new CustomFilter();
}
public void transforData(List items) {
this.mObjects = items;
notifyDataSetChanged();
}
@Override
public int getCount() {
return mObjects.size();
}
@Override
public String getItem(int position) {
return mObjects.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.simple_dropdown_item_1line, null);
viewHolder.content = convertView.findViewById(R.id.text1);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.content.setText(mObjects.get(position));
return convertView;
}
class ViewHolder {
TextView content;
}
@Override
public Filter getFilter() {
return mFilter;
}
private class CustomFilter extends Filter {
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (mLock) {
mOriginalValues = new ArrayList<>(mObjects);
}
}
int count = mOriginalValues.size();
ArrayList values = new ArrayList<>();
for (int i = 0; i < count; i++) {
String value = mOriginalValues.get(i);
if (null != value && null != constraint
&& value.toLowerCase().contains(constraint.toString().toLowerCase())) {
values.add(value);
}
}
results.values = values;
results.count = values.size();
return results;
}
@Override
protected void publishResults(CharSequence arg0, FilterResults results) {
mObjects = (List) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
根据需求修改performFiltering方法即可