如何在AutoCompleteTextView中使用的ArrayAdapter上移除过滤器?

5
作为标题所述,我该如何在使用AutoCompleteTextView的ArrayAdapter上移除过滤,以获取原始列表?
更多背景信息:
一切始于一个令人沮丧的事实,即传递给onItemClick()的“position”值是无用的。这个“position”指的是数组被过滤后的位置,但我需要知道它的真实位置。因此,我尝试的做法是当我得到所选项目的文本(使用getItemAtPosition(position)),将其逐一与支撑ArrayAdapter的原始字符串数组进行比较。然而,我发现当onItemClick()被调用时,适配器已经被过滤了,我不再能够访问原始数组。所以,我想如果我能够移除过滤,也许我就可以重新获取原始数组,并在其中查找所选项目。
ArrayAdapter<String> mAdapter;

public void onCreate() {

    // Create an adapter and remembere it as a class member.
    mAdapter = new ArrayAdapter<String>(this, layoutId);

    // Add 100 strings to it and attach it to an AutoCompleteTextView
    for (int i = 0; i < 100; i++)
        mAdapter.add("random text");
    ((AutoCompleteTextView)findViewById(id)).setAdapter(mAdapter);
}

@Override
public void onItemClick(AdapterView<?> actv, View view, int position, long id) {

    if (actv.getAdapter().equals(mAdapter))
        Log.d("The adapter contained in actv is the same one I created earlier.");

    // And, I can get the text of the item the user selected

    String selected = (String)actv.getItemAtPosition(position);

    // However, although the adapter passed in is still the same one, but the  
    // number of items in it is only 1! Because the array has been filtered.

    int numItems = actv.getAdapter.getCount();

    // So, I'm thinking if I can somehow remove the filtering here, then I can
    // get back those 100 items, and do a search like following:

    for (int i = 0; i < actv.getAdapter.getCount(); i++)
       if (selected == actv.getAdapter.getItem(i))
            break;    // Eureka!!!
}

解决获取所选项目的真实位置问题的方法:
  1. 是否有一种方法可以利用"id"值?比如,为每个项目分配一个id,然后希望onItemClick()会传回正确的id。

  2. 像我上面说的那样,删除过滤器(可能吗),恢复原始的100个项目,并逐个进行搜索。

  3. 这是最后的手段,我知道它会起作用,但我不想这样做:一旦我得到所选文本的文本,我就返回数据源(来自数据库)的源代码,查询那100个项目,并执行搜索。

  4. 另一个可怜的最后手段:为了避免在#3中再次访问数据库时的开销,在onCreate()中创建ArrayAdapter时,我使用自己的ArrayList来记住所有这些100个字符串。

我做错了吗?从AutoCompleteTextView获取所选项目的真实位置的“正确”方法是什么?

非常感谢!

(我在某个地方读到过,似乎是来自Google Android团队的某个人说应该使用getFirstVisiblePosition()来解决位置问题。但我无法弄清楚如何做到。)


我正在这里做类似的事情!!! https://dev59.com/Y-o6XIcBkEYKwwoYPR_f - Etienne Lawlor
4个回答

2

1

这个问题其实很简单解决。不要在获取每个元素时将其添加到适配器中(我假设你的随机文本部分只是举例),而是使用以下方法:

首先将数组构建成一个变量,称之为myArray.. 然后像这样初始化你的适配器:

mAdapter = new ArrayAdapter<String>(this, layoutId, myArray);

现在确保myArray是一个类变量,这样你就可以从类的任何其他地方引用它。当然,如果你需要从另一个类访问它,你需要为它创建一个getter... 然后你可以轻松地遍历数组,查看所选值是否在数组中... 你将拥有整个数据集,而不是试图从适配器中获取它。

这里有一个关于使用验证器的好例子,适用于类似的用例: Android, Autocomplettextview, force text to be from the entry list


我想我说得有点太早了.. 我很困惑你为什么要将每个元素添加到适配器中(它内部会创建自己的数据结构,但你不愿意创建自己的数据结构来存储数据)... 如果你真的担心资源问题,应该使用CursorAdapter,如果数据来自数据库... 还要注意,在我发送给你的示例中,数组已经排序,你可以使用二分搜索来检查值是否在数组中 -- O(log n)而不是O(n)。 - Matt Wolfe

0
在我的情况下,地址可以通过自动完成或点击地图来设置。如果用户点击地图,则应将editText文本设置为从地图选择的地址,并且在这种情况下,过滤应该暂时禁用。
我编写的代码如下:
public void OnAddressFound(String address) {
                // Temporary disable autocomplete
                editTextSearch.setAdapter(null);
                editTextSearch.setText(address);
                // Enable autocomplete again
                setAutoCompleteAdapter();
            }

在onCreate期间调用setAutoCompleteAdapter(),并在临时禁用/启用过滤器时再次调用:

void setAutoCompleteAdapter() {
    PlacesAutoCompleteAdapter adapter = new PlacesAutoCompleteAdapter(this, R.layout.item_autocomplete_map_search, autoCompleteList);
    editTextSearch.setAdapter(adapter);
    adapter.notifyDataSetChanged();
}

希望这也对你有所帮助。


0

我找到了解决方案,有点棘手但它有效。

在查看源代码后,我发现阈值变量用于过滤验证,我们只需要将阈值设置为最大整数,这样过滤就不会执行。

threshold = Integer.MAX_VALUE

或者

setThreshold(Integer.MAX_VALUE)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接