【问题标题】:AutoCompleteTextView item selection programmatically以编程方式选择 AutoCompleteTextView 项目
【发布时间】:2017-12-11 07:15:44
【问题描述】:

我有一个AutoCompleteTextView,其中包含来自 sqlite 数据库的城市,该数据库在单击项目时调用 AsyncTask,最近我添加了一个使用 gps 检测我的位置的选项,所以问题是我可以检测到城市(即贝鲁特)并为AutoCompleteTextView 设置文本但问题是下拉过滤器打开显示贝鲁特(这是正确的)但我仍然需要单击列表项来调用侦听器,如何以编程方式执行此操作

如何:

  • 输入活动(完成)
  • 检测位置(完成)
  • 设置文本视图的文本 (DONE)
  • 显示文本视图下拉列表(完成)
  • 选择要退回的商品,因为它只会退回一个城市(未完成)

【问题讨论】:

    标签: android adapter autocompletetextview


    【解决方案1】:

    需要明确的是,Tano 的解决方案足以回答这个问题。但是,如果其他人遇到与我相同的用例,这里有一些可能对您有所帮助的背景知识...

    我在尝试制作不可编辑的Material Exposed Dropdown Menu 并以编程方式设置它的初始值时特别遇到了这个问题。创建这种类型的“下拉菜单”的文档可以在暴露的下拉菜单部分here 中找到,它建议使用TextInputLayoutAutocompleteTextView 的机制(即使您不想要自动完成功能)。

    失败的解决方案 1: 乍一看setListSelection()getListSelection() 似乎他们可以做到这一点。但是经过多次尝试,我了解到它们可能还不够,因为它们仅在列表弹出isShowing() 时才有效。因此,例如,如果您只是想设置初始选择而不必先显示列表弹出窗口,这将不起作用。

    失败的解决方案 2: 然后我尝试了setText(),它在我的文本框中显示了正确的文本。耶!可是等等!当我单击文本视图时,出于某种原因,仅显示了列表弹出窗口中的一部分选项。那是为什么?这里要记住的关键是,由于这是一个自动完成文本视图,默认情况下它会根据文本视图中的文本过滤选项。这可能并不明显,特别是如果您只是为了制作一个简单的不可编辑的下拉选择器而使用此控件。

    解决方案: 这将我们带到了我们的实际解决方案(由 Tano 建议)...setText()filter 作为 false 将关闭过滤功能,并且不会更改列表弹出窗口的内容。

    autoCompleteTextView.setText(myText, false);
    

    【讨论】:

    • 我也在尝试使用自动完成文本视图来创建一个很好的下拉菜单,它的行为就像一个 Spinner(减去恼人的听众触发但具有漂亮的轮廓外观 textinputlayout 提供)。这里的解决方案可以根据文本设置选定的项目,但我希望在您触摸自动完成时所有可用的选项。现在我仍然必须删除文本才能让它们全部出现。有任何想法吗?或者有没有办法让 Spinner 看起来像概述的 textinputlayout?
    • 这是一个绝妙的答案,并且解释得很好。我唯一的问题是过滤器选项需要 17 的 API 级别
    • @JPM,可以随时显示下拉列表,见stackoverflow.com/a/26036902/2914140。目前,即使输入了一些文本,它也会打开完整列表(第一次)。编辑文本时,它会过滤项目。也许stackoverflow.com/a/60791879/2914140 有效,没有检查。
    • 我在此处提到的失败解决方案上花了几个小时,在开发了 8 年的 Android 应用程序之后,现在我离职业转变如此接近了。
    【解决方案2】:

    我遇到了类似的问题,这解决了我的问题。重要的是调用setText(<text>, <filter boolean>),以便不使用给定文本进行过滤,将第二个参数设置为false。文本将从下拉适配器中获取。

    解决方案sn-p:

    automCompleteTextView.setText(automCompleteTextView.getAdapter().getItem(position).toString(), false);
    

    【讨论】:

    • 谢谢!我认为,false 是默认值。所以,我们可以使用autoCompleteTextView.setText(someText);
    【解决方案3】:

    解决方案是您无需更改 API 级别。

    automCompleteTextView.setAdapter(adapter);        
    // set default selection, filtering is active so all items is not visible in drop-down menu
    automCompleteTextView.setText(automCompleteTextView.getAdapter().getItem(0).toString());
    // change filtering for the adapter so all items can be visible in drop-down menu
    adapter.getFilter().filter(null);
    

    同一工作的单线,但需要更高的 API 级别

    automCompleteTextView.setText(automCompleteTextView.getAdapter().getItem(0).toString(), false);
    

    【讨论】:

      【解决方案4】:

      我在深入了解android源代码上的AutoCompleteTextView代码后发现:

      fun AutoCompleteTextView.selectItem(text: String, position: Int = 0) {
        this.setText(text)
        this.showDropDown()
        this.setSelection(position)
        this.listSelection = position
        this.performCompletion()
      }
      

      【讨论】:

      • 谢谢!我删除了setSelection(position),因为它抛出了java.lang.IndexOutOfBoundsException: setSpan (43 ... 43) ends beyond length 34this. 也是不必要的。
      【解决方案5】:
      autoComplete.setListSelection(position);
      

      【讨论】:

        【解决方案6】:

        尝试在 AutoCompleteTextview 中的 setText() 之后添加以下内容:-

        autoCompleteTV.setSelection(position);
        

        更新:

        这将适用于具有下拉功能的SpinnerAutoCompleteTextView,但不适用于EditText

        您可以在此链接中查看 AbsSpinner 的文档: https://developer.android.com/reference/android/widget/AbsSpinner.html#setSelection(int)

        【讨论】:

        • @HusseinYassine 让我检查一下我的工作,并提供解决方案。
        • setSelection 是光标放置位置的简写,而不是在适配器中选择项目。
        • @Chris.Jenkins 为了您的澄清,请检查此链接developer.android.com/reference/android/widget/… 初始化后仍然没有得到然后尝试不同的位置。
        • @NitinPatel 是的,AbstractSpinnerAutoCompleteTextView 不是那样。 setSelection 上的 EditText 设置光标位置而不是微调器中的项目选择。
        • @Chris.Jenkins 我同意你的看法。这就是秘密。
        【解决方案7】:

        我也使用过autoCompleteTextView.setText(myText, false); 解决方案,但有时会失败。我的意思是它正在积极过滤结果,所以当用户点击时,下拉菜单中只有一项。

        此外,我还需要它来处理自定义对象,这是我的解决方案:

        binding.hourEditText.configureDropDownMenu(viewModel.hours) { it.hourString() }
            .subscribe {
                // Do whatever you need when on click.
            }
            .addTo(disposables)
        
        fun <T> AutoCompleteTextView.configureDropDownMenu(list: List<T>, toString: ((T) -> String)? = null): Observable<T> {
            keyListener = null
            val textItems = toString?.let(list::map) ?: list.map { it.toString() }
            setAdapter(NonFilterArrayAdapter(context!!, android.R.layout.simple_spinner_dropdown_item, textItems))
            return itemClickEvents().map {
                list[it.position]
            }
        }
        
        private class NonFilterArrayAdapter<T>(context: Context, @LayoutRes resource: Int, objects: List<T>) : ArrayAdapter<T>(context, resource, objects) {
        
            override fun getFilter() = NonFilter()
        
            private class NonFilter : Filter() {
                override fun performFiltering(constraint: CharSequence?) = FilterResults()
        
                override fun publishResults(constraint: CharSequence?, results: FilterResults?) = Unit
            }
        }
        

        注意:这里也包含了一点Rx,但是很容易去掉。

        【讨论】:

          【解决方案8】:

          问题是您正在设置文本,而 AutoCompleteTextView 仅显示与该文本匹配的单词。解决此问题的一种非优雅方法是设置一个高阈值(至少是城市名称的最大长度)以强制 Android 向您显示列表的所有值(此阈值是该字段必须包含的字符数必须搜索相似之处)。

          【讨论】:

            【解决方案9】:

            使用Nilton Vasques 解决方案可以这样:

            with(autoComplete) {
                setAdapter(this@YourFragment.adapter)
                setText(itemText)
                showDropDown()
                listSelection = if (itemIndex > 0) itemIndex - 1 else 0 // Because AutoCompleteTextView shows the next row.
                performCompletion()
            }
            

            注意,它会显示一个下拉列表,否则listSelection 将不起作用。如果您调用dismissDropDown(),该项目将不会被选中。如果您不想显示下拉列表,可以使用setOnTouchListener 捕获打开列表,但这几乎没有帮助(您应该解决过滤问题)。

            setOnTouchListener { _, event ->
                if (event.action == MotionEvent.ACTION_DOWN) {
                    showDropDown()
                    listSelection = if (itemIndex > 0) itemIndex - 1 else 0
                    performCompletion()
                    requestFocus()
                }
                false
            }
            

            【讨论】:

              猜你喜欢
              • 2014-03-02
              • 2012-07-17
              • 2013-12-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-07-09
              相关资源
              最近更新 更多