AutoCompleteTextView(可实现模糊搜索)

本文介绍了如何在Android中使用AutoCompleteTextView实现模糊搜索功能,通过自定义WordAdapter类和添加过滤器,实现在用户输入时动态显示匹配的单词建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  

目录

介绍

xml属性

定义一个单词类

编辑xml文件

编写适配器

一个基础的适配器

添加过滤器(用于根据自己的规则实现模糊搜索)

在活动中使用

实现效果


      本文作者通过对AutoCompleteTextView使用,来实现对单词的模糊搜索。        

介绍

        AutoCompleteTextView是Android中的一个视图控件,它是EditText和ListView的组合。它提供了自动完成文本输入的功能,并显示与用户输入相匹配的建议列表。

AutoCompleteTextView的主要特性和用途如下:

  1. 自动完成功能:AutoCompleteTextView通过监视用户的文本输入,在用户输入时自动弹出与输入内容相匹配的建议列表。用户可以从列表中选择一个建议项,或继续输入以缩小建议列表。

  2. 建议列表:AutoCompleteTextView的下拉列表显示与用户输入相匹配的建议项。建议项通常是基于预定义的数据源(例如数组、数据库查询结果等)生成的,也可以通过自定义适配器来提供。

  3. 自定义适配器:可以使用自定义适配器来控制建议列表的显示方式和内容。通过扩展ArrayAdapterCursorAdapter等适配器类,可以自定义建议列表的外观和数据源。

  4. 异步数据加载:AutoCompleteTextView支持异步加载建议数据。可以在后台线程中执行数据的获取和处理,并在数据准备好后更新建议列表。

  5. 文本过滤:AutoCompleteTextView可以根据用户的输入进行过滤,只显示与输入内容匹配的建议项。过滤可以基于前缀匹配、全文匹配等方式进行。

  6. 事件监听:AutoCompleteTextView可以设置文本变化监听器(TextWatcher),以便在用户输入文本时执行特定的操作。可以根据用户的输入动态更新建议列表或执行其他相关操作。

  7. 自定义样式和布局:可以通过在布局文件中使用自定义的样式和布局属性,对AutoCompleteTextView进行外观上的自定义,以使其与应用程序的设计风格一致。

xml属性

android:completionHint:设置下拉菜单中的提示标题
android:completionHintView:定义提示视图中显示下拉菜单
android:completionThreshold:指定用户至少输入多少个字符才会显示提示
android:dropDownAnchor:设置下拉菜单的定位"锚点"组件,如果没有指定改属性, 将使用该TextView作为定位"锚点"组件
android:dropDownHeight:设置下拉菜单的高度
android:dropDownWidth:设置下拉菜单的宽度
android:dropDownHorizontalOffset:指定下拉菜单与文本之间的水平间距
android:dropDownVerticalOffset:指定下拉菜单与文本之间的竖直间距
android:dropDownSelector:设置下拉菜单点击效果
android:popupBackground:设置下拉菜单的背景
 

定义一个单词类

public class Vocabulary {
    public String word;
    public Vocabulary() {
    }

编辑xml文件

<AutoCompleteTextView
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:id="@+id/autoComplete_word"
     android:hint="查询单词"
     android:completionThreshold="2"
     android:dropDownHeight="wrap_content"
     android:dropDownWidth="wrap_content"/>

编写适配器

        模糊搜索结果的展示是一个ListView或者RecycleView,同时还需要根据自己需求来定义模糊搜索的规则,所以需要我们实现一个自己的适配器。这里我使用的是ListView,所以定义了ListView的适配器。

一个基础的适配器

定义一个WordAdapter类,代码如下:

public class WordAdapter extends ArrayAdapter<Vocabulary> {
    private int layoutRes;
    private List<Vocabulary> originalList = null;
    private List<Vocabulary> filteredList;

    public WordAdapter(@NonNull Context context, int resource, @NonNull List<Vocabulary> objects) {
        super(context, resource, objects);
        layoutRes = resource;
        originalList = new ArrayList<>(objects);
        filteredList = new ArrayList<>();
    }


    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        Vocabulary vocabulary = getItem(position);
        View view;
        ViewHolder viewHolder;
        if (convertView == null){
            view = LayoutInflater.from(getContext()).inflate(layoutRes,parent,false);
            viewHolder = new ViewHolder();
            viewHolder.textView = (TextView) view.findViewById(R.id.word);
            view.setTag(viewHolder);
        }else {
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }
        viewHolder.textView.setText(vocabulary.word);
        return view;
    }
    class ViewHolder{
        TextView textView;
    }
}

添加过滤器(用于根据自己的规则实现模糊搜索)

在WordAdapter内重写三个方法,代码如下:

@Override
    public int getCount() {
        return filteredList.size();
    }

    @Nullable
    @Override
    public Vocabulary getItem(int position) {
        return filteredList.get(position);
    }

    @NonNull
    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                FilterResults results = new FilterResults();
                filteredList.clear();
                if (charSequence == null || charSequence.length() == 0){
                }else {
                    String filterPattern = charSequence.toString().toLowerCase().trim();
                    for (Vocabulary item : originalList){
                        if (item.word.contains(filterPattern))
                            filteredList.add(item);
                    }
                }
                results.values = filteredList;
                results.count = filteredList.size();
                return results;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                if (filterResults != null && filterResults.count > 0) {
                    clear();
                    addAll((List<Vocabulary>) filterResults.values);
                    notifyDataSetChanged();
                }
//                if (filterResults != null && filterResults.count > 0) {
//                    notifyDataSetChanged();
//                } else {
//                    notifyDataSetInvalidated();
//                }
            }
        };
    }
if (item.word.contains(filterPattern))
    filteredList.add(item);

        这段代码就把可以集合中=item.word字段内含有filterPattern的所有元素过滤出来,当然,你也可以使用starWith过滤。

        注意,一定要重写getItem()和getCount()方法,否则会出错。我也是因为这个问题,改了很久。

下面是WordAdapter的完整代码:

public class WordAdapter extends ArrayAdapter<Vocabulary> {
    private int layoutRes;
    private List<Vocabulary> originalList = null;
    private List<Vocabulary> filteredList;

    public WordAdapter(@NonNull Context context, int resource, @NonNull List<Vocabulary> objects) {
        super(context, resource, objects);
        layoutRes = resource;
        originalList = new ArrayList<>(objects);
        filteredList = new ArrayList<>();
    }


    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        Vocabulary vocabulary = getItem(position);
        View view;
        ViewHolder viewHolder;
        if (convertView == null){
            view = LayoutInflater.from(getContext()).inflate(layoutRes,parent,false);
            viewHolder = new ViewHolder();
            viewHolder.textView = (TextView) view.findViewById(R.id.word);
            view.setTag(viewHolder);
        }else {
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }
        viewHolder.textView.setText(vocabulary.word);
        return view;
    }
    class ViewHolder{
        TextView textView;
    }

    @Override
    public int getCount() {
        return filteredList.size();
    }

    @Nullable
    @Override
    public Vocabulary getItem(int position) {
        return filteredList.get(position);
    }

    @NonNull
    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                FilterResults results = new FilterResults();
                filteredList.clear();
                if (charSequence == null || charSequence.length() == 0){
                }else {
                    String filterPattern = charSequence.toString().toLowerCase().trim();
                    for (Vocabulary item : originalList){
                        if (item.word.contains(filterPattern))
                            filteredList.add(item);
                    }
                }
                results.values = filteredList;
                results.count = filteredList.size();
                return results;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                if (filterResults != null && filterResults.count > 0) {
                    clear();
                    addAll((List<Vocabulary>) filterResults.values);
                    notifyDataSetChanged();
                }
            }
        };
    }
}

在活动中使用(这里其实我是在碎片中使用的)

        AutoCompleteTextView autoText = (AutoCompleteTextView) view.findViewById(R.id.autoComplete_word);
        getWordList();//这是我的自定义方法,在数据库中获取单词集合

        WordAdapter adapter = new WordAdapter(getContext(),R.layout.word_item,wordList);

        autoText.setAdapter(adapter);

        autoText.setOnItemClickListener(new AdapterView.OnItemClickListener() {//设置item的点击事件
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                ArrayAdapter<Vocabulary> arrayAdapter = (ArrayAdapter<Vocabulary>) adapterView.getAdapter();
                Vocabulary vocabulary = arrayAdapter.getItem(i);
                Intent intent = new Intent(getContext(),ShowWordActivity.class);
                intent.putExtra("word",vocabulary.word);
                startActivity(intent);
            }
        });

实现效果

        这里我用的是contains()方法,你也可以采用startWith()方法过滤。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值