【Android】【自定义控件】自动填充输入框,自定义AutoCompleteTextView

android自带的AutoCompleteTextView,可以简单地实现自动补全功能,但是限制较多
这里介绍如何通过自定义来扩展AutoCompleteTextView功能,包括以下功能

  • 解决最小字符匹配数量限制,零个字符时也可提示全部选项
  • 自定义匹配规则,可以自己通过代码实现拼音匹配,模糊匹配等功能
  • 集成Adapter,不用再创建Adapter,直接传入一个选项数组即可

AutoCompleteEdit


//自动补全输入框
public class AutoCompleteEdit extends AppCompatAutoCompleteTextView {

    private int threshold = 0;

    private FilterableTextAdapter adapter;

    public AutoCompleteEdit(Context context) {
        super(context);
        init();
    }

    public AutoCompleteEdit(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public AutoCompleteEdit(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {

        //下拉项适配器
        adapter = new FilterableTextAdapter();
        adapter.autoCompleteEdit = this;
        setAdapter(adapter);

        //文字改变时,更新建议项
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                adapter.getFilter().filter(s);
            }
        });

        //获得焦点时,更新建议项
        setOnFocusChangeListener((v, hasFocus) -> {
            if (hasFocus)
                showDropDown();
        });

        //有焦点重新点击时,也更新建议项
        setOnClickListener(v -> {
            if (getText().toString().isEmpty())
                showDropDown();
        });
    }

    @Override
    public boolean enoughToFilter() {
        return getText().length() >= threshold;
    }

    //设置字符匹配数量
    public AutoCompleteEdit threshold(int threshold) {
        this.threshold = threshold;
        return this;
    }

    //更新全部可选数据
    public AutoCompleteEdit reset(List<String> datas) {
        adapter.reset(datas);
        return this;
    }

    //下拉选项更新时,执行回调
    public AutoCompleteEdit onFilter(FilterableTextAdapter.OnFilter onFilter) {
        adapter.onFilter((items, count) -> {
            setDropDownHeight(600);
            showDropDown();
        });
        return this;
    }

}

FilterableTextAdapter


//带数据过滤功能的TextAdapter
public class FilterableTextAdapter extends BaseAdapter implements Filterable {

    protected AutoCompleteEdit autoCompleteEdit;

    private List<String> originItems = new ArrayList();
    private List<String> filteredItems = new ArrayList();

    private TextFilter filter = new TextFilter();

    private OnFilter onFilter;

    public void onFilter(OnFilter onFilter) {
        this.onFilter = onFilter;
    }

    public int getCount() {
        return filteredItems.size();
    }

    @Override
    public String getItem(int position) {
        return filteredItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View root = ViewManager.inflate(parent.getContext(), R.layout.item_text_list);
        TextView text = root.findViewById(R.id.tv);
        text.setText(getItem(position));
        //点击设置文本,并关闭下拉框
        root.setOnClickListener(v -> {
            autoCompleteEdit.setText(text.getText());
            autoCompleteEdit.setSelection(text.getText().length());
            autoCompleteEdit.dismissDropDown();
        });
        return root;
    }

    @Override
    public Filter getFilter() {
        return filter;
    }

    //重置全部可选数据
    public void reset(List<String> items) {
        originItems.clear();
        originItems.addAll(items);
    }

    //文本过滤器,用于定义匹配规则,更新匹配项
    public class TextFilter extends Filter {

        //数据过滤
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            String key = constraint.toString().toLowerCase();
            List<String> temp = new ArrayList();
            //如果没有限制,则显示全部
            if (constraint.toString().isEmpty()) {
                temp.addAll(originItems);
                FilterResults results = new FilterResults();
                results.values = temp;
                results.count = temp.size();
                return results;
            }
            //如果不是拼音,以关键字开头,或包含关键字,则匹配
            for (String item : originItems) {
                if (item.toLowerCase().startsWith(key))
                    temp.add(item);
            }
            for (String item : originItems) {
                if (item.toLowerCase().contains(key) && !temp.contains(item))
                    temp.add(item);
            }
            //如果是拼音,拼音以关键字开头,或简拼以关键字开头,则匹配
            if (key.matches("^[a-z]+$")) {
                for (String item : originItems) {
                    if (TextUtil.getSimplePinyin(item).startsWith(key) && !temp.contains(item))
                        temp.add(item);
                }
                for (String item : originItems) {
                    if (TextUtil.getPinyin(item).contains(key) && !temp.contains(item))
                        temp.add(item);
                }
            }
            //封装过滤结果
            FilterResults results = new FilterResults();
            results.values = temp;
            results.count = temp.size();
            return results;
        }

        //发布过滤结果
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            //根据过滤结果去更新adapter
            if (results.count == 0)
                notifyDataSetInvalidated();
            else {
                filteredItems = (List<String>) results.values;
                notifyDataSetChanged();
            }
            //执行回调
            if (onFilter != null)
                onFilter.OnFilter((List<String>) results.values, results.count);
        }
    }

    public interface OnFilter {

        void OnFilter(List<String> items, int count);
    }

}

LoginActivity


public class LoginActivity extends CommonActivity<LoginActivity> {

    @BindView(R.id.edit)
    AutoCompleteEdit edit;

    protected void create() {
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this, ctx);
        init();
    }

    private void init() {
        List<String> datas = new LinkedList();
        datas.add("ABC");
        datas.add("abc");
        datas.add("中国人");
        datas.add("abc中国人");
        datas.add("中国人abc");
        edit.reset(datas);
    }

}

上面部分功能用到了工具类,需要自己修改,但是核心代码全部齐备,可以轻松修改

运行效果
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值