【问题标题】:SearchView fires only the second time when using a filter in ArrayAdapter在 ArrayAdapter 中使用过滤器时,SearchView 仅第二次触发
【发布时间】:2019-09-11 10:47:33
【问题描述】:

我在工具栏中添加了一个 SearchView 来过滤一些项目。

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.menu, menu);
    MenuItem searchItem = menu.findItem(R.id.search);
    SearchView search = (SearchView) searchItem.getActionView();
    autoComplete = search.findViewById(androidx.appcompat.R.id.search_src_text);
}

在我的 MainActivity 中,我得到一个项目列表并将其传递给我的适配器:

ItemsArrayAdapter adapter = new ItemsArrayAdapter(this, itemList);
autoComplete.setAdapter(adapter);

这是我的适配器类:

public class ItemsArrayAdapter extends ArrayAdapter<Item> {
    private List<Item> itemListFull;

    ItemsArrayAdapter(@NonNull Context context, @NonNull List<Item> items) {
        super(context, 0, items);
        itemListFull = new ArrayList<>(items);
    }

    @NonNull
    @Override
    public Filter getFilter() {
        return itemFilter;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        Item item = getItem(position);
        if (convertView == null) {
            //Inflate view
        }
        return convertView;
    }

    private Filter itemFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            List<Item> suggestionList = new ArrayList<>();
            if (constraint == null || constraint.length() == 0) {
                suggestionList.addAll(itemListFull);
            } else {
                String filterPattern = constraint.toString().toLowerCase().trim();
                for (Item item : itemListFull) {
                    if (item.name.toLowerCase().contains(filterPattern)) {
                        suggestionList.add(item);
                    }
                }
            }
            results.values = suggestionList;
            results.count = suggestionList.size();
            Log.d(TAG, "size: " + suggestionList.size());
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            List<Item> items = (List<Item>) results.values;
            if (items != null) {
                clear();
                addAll(items);
            }
            notifyDataSetChanged();
        }

        @Override
        public CharSequence convertResultToString(Object resultValue) {
            return ((Item) resultValue).name;
        }
    };
}

列表中存在的项目数是 26。当我从单词 car 写一封信时,例如 c,返回的项目数是 26,即使包含 c 的单词是只有 11. 当我键入第二个字母 a 时,返回的项目数为 1(这是正确的),并且项目在视图中正确显示。如何使 SearchView 触发并从第一次返回正确数量的项目?谢谢。

【问题讨论】:

  • 你在哪里打电话给Filter
  • @MikeM。我只在我的MainActivity 中添加ItemsArrayAdapter adapter = new ItemsArrayAdapter(this, itemList);autoComplete.setAdapter(adapter);。我没有调用任何过滤器。
  • 酷。不过,让我看看我们是否可以在没有受限 API 调用的情况下做到这一点。稍后我会在有时间的时候再次查看源代码。很高兴我们得到了一些工作,无论如何。干杯!
  • @MikeM。如果我可以在没有受限 API 调用的情况下使用它,那就太好了。再次感谢。
  • 好的,我认为我们可以在没有限制调用的情况下做到这一点,但它必须通过一种风格:drive.google.com/file/d/11t8qB357t4OIm6Dm9RPuqvvKplRA1lAA/…。我没有可用的 androidx 设置,atm,所以请在闲暇时进行测试。如果它对你有用,我会写一个答案,但可能要到今晚很晚。

标签: android android-arrayadapter android-search android-filter


【解决方案1】:

SearchView 中的 search_src_textAutoCompleteTextView 的后代,它从该类继承了大部分行为。 AutoCompleteTextView 的默认阈值为 2 个字符。也就是说,在您输入至少 2 个字符之前,它不会开始过滤,这就解释了为什么您在只输入一个字符时会看到完整的列表。我们可以通过将阈值降低到 1 来解决这个问题。

AutoCompleteTextView 具有 setThreshold() 方法,因此我们可以简单地使用参数 1 调用它。但是,正如您所指出的,这会导致 can only be called from within the same library group lint 警告,因为 androidx SearchView 的特定子类使用在源代码中标记为@hide。这可以通过@SuppressLint("RestrictedApi") 轻松抑制,但如果您不想使用受限 API,还有另一种方法。

我们可以通过在默认AutoCompleteTextView 样式的子样式中指定的android:completionThreshold XML 属性设置该阈值,然后我们在Activity 的主题中将其设置为autoCompleteTextViewStyle。那就是:

<style name="AppTheme" parent="...">
    ...
    <item name="autoCompleteTextViewStyle">@style/LowThreshold.AutoCompleteTextView</item>
</style>

<style name="LowThreshold.AutoCompleteTextView" parent="Widget.AppCompat.AutoCompleteTextView">
    <item name="android:completionThreshold">1</item>
</style>

注意autoCompleteTextViewStyle 属性没有android 前缀,因为SearchView 中的实际类是AppCompatAutoCompleteTextView 的子类,它有自己的默认样式属性。

【讨论】:

    猜你喜欢
    • 2021-03-14
    • 1970-01-01
    • 2021-04-29
    • 2013-10-15
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    相关资源
    最近更新 更多