Android: 当AutoCompleteTextView没有输入文本时显示建议

141

我正在使用AutoCompleteTextView,当用户点击它时,即使没有输入文本,我也希望显示建议 - 但是setThreshold(0)的效果与setThreshold(1)完全相同 - 因此用户必须至少输入1个字符才能显示建议。


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

176

这是已记录的行为

threshold小于或等于0时,应用1的阈值。

您可以通过showDropDown()手动显示下拉菜单,因此当您需要时可以安排显示它。或者,子类化AutoCompleteTextView并覆盖enoughToFilter(),始终返回true


8
showDropDown() 在设置 onClickListener 方面似乎运行良好,但子类的事情直到用户输入一个字母并删除回退后才开始工作。但不仅仅是 onClick... - amj
10
当与OnFocusChangeListener结合使用并在视图获得焦点时调用showDropDown()时,这个方法就能完美地发挥作用。 - Grishka
我还必须重写onFocusChanged,正如下面@David Vávra的答案所述。 - Gabriel
5
为什么在 afterTextChanged 中,当 .getText().toString().length() == 0 时,showDropDown() 方法无法正常工作? - Prabs
1
只有重写 enoughToFilter 方法才能帮到我。谢谢! - Fedir Tsapana
运行得非常好。使用setOnFocusChangeListener,然后在AutocompleteTextView上调用showDropDown()。 - M Umer

137

这是我的类InstantAutoComplete。它介于AutoCompleteTextViewSpinner之间。

import android.content.Context;  
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.AutoCompleteTextView;

public class InstantAutoComplete extends AutoCompleteTextView {

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

    public InstantAutoComplete(Context arg0, AttributeSet arg1) {
        super(arg0, arg1);
    }

    public InstantAutoComplete(Context arg0, AttributeSet arg1, int arg2) {
        super(arg0, arg1, arg2);
    }

    @Override
    public boolean enoughToFilter() {
        return true;
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction,
            Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (focused && getAdapter() != null) {
            performFiltering(getText(), 0);
        }
    }

}

在您的xml中使用它,就像这样:

<your.namespace.InstantAutoComplete ... />

12
太好了!我还想指出,在您的布局XML文件中,您需要将<AutoCompleteTextView ... />更改为<your.namespace.InstantAutoComplete ... />。我浪费了一些时间才弄明白这一点 :) - Jules Colle
3
好的,我会尽力进行翻译。建议您在onFocusChanged方法中,将“if(focused)”修改为“if(focused && getAdapter() != null)”,以提高代码的稳定性。 - Jacob Tabak
对于 AndroidX,请扩展 androidx.appcompat.widget.AppCompatAutoCompleteTextView - Mahmudul Hasan Shohag

55

最简单的方法:

只需使用setOnTouchListener并调用showDropDown()

AutoCompleteTextView text;
.....
.....
text.setOnTouchListener(new View.OnTouchListener(){
   @Override
   public boolean onTouch(View v, MotionEvent event){
      text.showDropDown();
      return false;
   }
});

1
为了让它更好,使用 if(!text.isPopupShowing()){ text.showDropDown(); } - Boldijar Paul
7
虽然不太常见,但如果用户不触摸EditText就不能使用。例如,当使用带有按钮的遥控器(例如Android电视)时。 - android developer
2
你应该使用setOnFocusChanged。有人可能会使用键盘并按TAB键,或者使用鼠标和触摸监听器不会被调用。 - barwnikk
onTouchListener 会在单次点击时被调用多次 - 例如:事件可以是 MotionEvent.ACTION_DOWN,MotionEvent.ACTION_UP。因此最好检查特定事件并编写代码。 - Govind
浪费了整整两天,你解决了我的问题,太感谢了。@user1913469 - Himani

18

Destil的代码在只有一个InstantAutoComplete对象时非常好用。但是当有两个对象时,它却无法工作-我不知道为什么。但是当我像CommonsWare建议的那样,在onFocusChanged()中加入了showDropDown()时,它就可以工作了:

@Override
protected void onFocusChanged(boolean focused, int direction,
        Rect previouslyFocusedRect) {
    super.onFocusChanged(focused, direction, previouslyFocusedRect);
    if (focused) {
        performFiltering(getText(), 0);
        showDropDown();
    }
}

问题已得到解决。

这只是两个答案的正确结合,但我希望它能节省某些人的时间。


2
你的添加有所帮助,但是如果InstantAutoComplete中有文本并且屏幕方向改变,我会收到一个错误。我通过检查窗口可见性来解决了这个问题,我在这里发布了新代码:https://gist.github.com/furycomptuers/4961368 - FuryComputers

11
适配器最初不执行过滤。
当未执行过滤时,下拉列表为空。
因此,您可能需要最初进行过滤。
为此,在添加条目后,可以调用filter()
adapter.add("a1");
adapter.add("a2");
adapter.add("a3");
adapter.getFilter().filter(null);

7

你可以使用onFocusChangeListener;

TCKimlikNo.setOnFocusChangeListener(new OnFocusChangeListener() {

        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                TCKimlikNo.showDropDown();

            }

        }
    });

7

Destil的答案几乎可以,但有一个微妙的错误。当用户首次聚焦于该字段时,它可以工作,但是如果他们离开并返回该字段,则不会显示下拉列表,因为mPopupCanBeUpdated的值仍将从隐藏时的false保持不变。修复方法是更改onFocusChanged方法:

@Override
protected void onFocusChanged(boolean focused, int direction,
        Rect previouslyFocusedRect) {
    super.onFocusChanged(focused, direction, previouslyFocusedRect);
    if (focused) {
        if (getText().toString().length() == 0) {
            // We want to trigger the drop down, replace the text.
            setText("");
        }
    }
}

但这也意味着文本将被重置(尽管通常这很好)... - android developer

5
只需在autoCompleteTextView的触摸或点击事件中调用此方法,或者您想要的任何位置。
autoCompleteTextView.showDropDown()

3
为了制作CustomAutoCompleteTextView。 1. 重写setThreshold、enoughToFilter、onFocusChanged方法。
public class CustomAutoCompleteTextView  extends AutoCompleteTextView { 

    private int myThreshold; 

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

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

    public CustomAutoCompleteTextView  (Context context, AttributeSet attrs) { 
        super(context, attrs); 
    } 
     //set threshold 0.
    public void setThreshold(int threshold) { 
        if (threshold < 0) { 
            threshold = 0; 
        } 
        myThreshold = threshold; 
    } 
    //if threshold   is 0 than return true
    public boolean enoughToFilter() { 
         return true;
        } 
    //invoke on focus 
    protected void onFocusChanged(boolean focused, int direction,
            Rect previouslyFocusedRect) {
                    //skip space and backspace 
        super.performFiltering("", 67);
        // TODO Auto-generated method stub
        super.onFocusChanged(focused, direction, previouslyFocusedRect);

    }

    protected void performFiltering(CharSequence text, int keyCode) {
        // TODO Auto-generated method stub
        super.performFiltering(text, keyCode);
    }

    public int getThreshold() { 
        return myThreshold; 
    } 
}

1
七年过去了,问题仍然存在。这是一个带有函数的类,可以在任何情况下强制显示该愚蠢的弹出窗口。您只需要将适配器设置为您的AutoCompleteTextView,添加一些数据,并随时调用showDropdownNow()函数即可。
感谢@David Vávra。它是基于他的代码。
import android.content.Context
import android.util.AttributeSet
import android.widget.AutoCompleteTextView

class InstantAutoCompleteTextView : AutoCompleteTextView {

    constructor(context: Context) : super(context)

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun enoughToFilter(): Boolean {
        return true
    }

    fun showDropdownNow() {
        if (adapter != null) {
            // Remember a current text
            val savedText = text

            // Set empty text and perform filtering. As the result we restore all items inside of
            // a filter's internal item collection.
            setText(null, true)

            // Set back the saved text and DO NOT perform filtering. As the result of these steps
            // we have a text shown in UI, and what is more important we have items not filtered
            setText(savedText, false)

            // Move cursor to the end of a text
            setSelection(text.length)

            // Now we can show a dropdown with full list of options not filtered by displayed text
            performFiltering(null, 0)
        }
    }
}

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