如何禁用AutoCompleteTextView的下拉框显示?

20
我使用以下代码将文本设置到AutoCompleteTextView字段中。但是我注意到,当我将某些文本(不是所有文本,而只是某些文本)设置给它时,它会自动弹出下拉菜单。如果我不请求焦点,情况会变得更好,但仍然不完全正确。我尝试了dismissDropDown(),但没有帮助。那么,在设置文本和聚焦后,有没有办法阻止下拉菜单显示?
actv.setText("Tim Hortons");
actv.setSelection(0, actv.getText().length());
actv.requestFocus();
actv.dismissDropDown();    // doesn't help

谢谢您!
19个回答

20

另一种解决方法是在设置文本之前清除焦点:

mContactTxt.setFocusable(false);
mContactTxt.setFocusableInTouchMode(false);
mContactTxt.setText("");            
mContactTxt.setFocusable(true);
mContactTxt.setFocusableInTouchMode(true);

18
您可以尝试以下步骤:
  1. 在设置文本时,同时将阈值设置为较大的值,以避免下拉菜单出现。

 actv.setThreshold(1000);
然后重写 OnTouch 方法将阈值重新设为 1。
   actv.setOnTouchListener(new OnTouchListener() {
                @Override
    public boolean onTouch(View v, MotionEvent event) {
        actv.setThreshold(1);
        return false;
    }
});

这会阻止搜索实际执行吗?还是只隐藏了下拉菜单? - Mauker
我发现在设置新文本后,我可以立即将阈值(在我的情况下为1)设回,它可以正常工作。我不需要触摸监听器。 - Dave Hubbard

14
为了回答自己的问题,如果有人也遇到同样的问题:
AutoCompleteTextView的一个特点是,如果您以编程方式更改其文本,则仅在符合以下两个条件时它将下拉选择列表:1. 它具有焦点;2. 列表超过30多个项目。
这种行为实际上是设计缺陷。当程序将文本设置为AutoCompleteTextView时,这意味着文本已经正确,没有必要弹出过滤列表供用户进一步选择。
actv.setText("Tim Hortons"); 
actv.setSelection(0, actv.getText().length()); 
actv.requestFocus(); 
actv.dismissDropDown();    // doesn't help 

在上面的代码中,requestFocus()强制ACTV获取焦点,这会导致下拉框弹出。我试图不请求焦点,而是在设置文本后调用clearFocus()。但是行为非常...不自然。dismissDropdown()无法解决问题,因为...我不知道,它就是不起作用。因此,在经过多次尝试后,我想出了这个解决方法:
  1. When initializing the widget, I remembered the adapter in a class field.
  2. Change the above code to:

    mAdapter = (ArrayAdapter<String>)actv.getAdapter(); // mAdapter is a class field        
    actv.setText("Tim Hortons"); 
    actv.setSelection(0, actv.getText().length()); 
    actv.setAdapter((ArrayAdapter<String>)null); // turn off the adapter
    actv.requestFocus();
    Handler handler = new Handler() {
    public void handleMessage(Message msg) {
        ((AutoCompleteTextView)msg.obj).setAdapter(mAdapter);
        };
    Message msg = mHandler.obtainMessage();
    msg.obj = actv;
    handler.sendMessageDelayed(msg, 200);   // turn it back on after 200ms
    

这里的技巧是将ACTV的适配器设置为null。因为没有适配器,当然系统不会弹出下拉菜单。但是消息将在200ms的编程延迟后将适配器重置回ACTV,然后ACTV将像往常一样正常工作。

这对我很有效!


这对我起作用了;我不需要设置编程延迟。 - terencey

13

您也可以像这样启用/禁用下拉菜单:

// disable
actv.setDropDownHeight(0);
// enable
actv.setDropDownHeight(LayoutParams.WRAP_CONTENT);

11
setText("someText",false)

false表示不进行过滤


哇,这对我非常有效,很有道理,而且简单得多。它应该是正确的答案。 - Mike
哈哈哈,我花了好几个小时才搞明白,结果原来问题就在我们每天都用的方法里的一个参数上,我的无知真是太可笑了...谢谢你,这才是正确的答案! - Bronz

7
也许已经有点晚了,但我找到了一个优雅的解决方案来解决这个问题:
在设置文本之前禁用过滤,在启用它之后(而不是使用焦点或延迟)。在这种情况下,您应该使用自定义控件。
请参见以下示例:
public class CustomCompliteTextView extends AutoCompleteTextView {

    private boolean mIsSearchEnabled = true;

    public CustomCompliteTextView(Context context) {
        super(context);
    }

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

    public CustomCompliteTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setSearchEnabled(boolean isEnabled) {
        mIsSearchEnabled = isEnabled;
    }

    @Override
    protected void performFiltering(CharSequence text, int keyCode) {
        if (mIsSearchEnabled) {
            super.performFiltering(text, keyCode);
        }
    }
}

使用方法:

    text.setSearchEnabled(false);
    text.setText("Text you want to set");
    // optional, if you also want to set correct selection
    text.setSelection(text.getText().length());
    text.setSearchEnabled(true);

4
有趣的技巧。百分之百可行 :)
tv.setThreshold(Integer.MAX_VALUE);
tv.setText(station.getName());
tv.setThreshold(1);

确实很有趣,但达到了目的。 - Adil Soomro
看起来很有趣,但是试一下。 - blackHawk

3
act.post(new Runnable() 
{
  @Override
  public void run()
  {
    act.dismissDropDown();
  }
});

运行正常!


2
你可以尝试:
searchInput.setAdapter((ArrayAdapter<String>) null);
searchInput.setText(text);
searchInput.setAdapter(adapter);

Source


2

wwyt,我只是借鉴了您移除适配器的技巧,以下是取消焦点/关闭下拉菜单的基本要素。

AutoCompleteTextView tvSuburbs;
ArrayAdapter<Suburb> a = (ArrayAdapter<Suburb>) tvSuburbs.getAdapter();
tvSuburbs.setAdapter(null); // Remove the adapter so we don't get a dropdown
tvSuburbs.setText(s.name); // when text is set programmatically.
tvSuburbs.setAdapter(a); // Restore adapter

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