Android: o AutoCompleteTextView mostra sugestões quando nenhum texto é inserido

127

Estou usando AutoCompleteTextView, quando o usuário clica nele, quero mostrar sugestões, mesmo que não possua texto - mas setThreshold(0)funcione exatamente da mesma forma que setThreshold(1)-, para que o usuário precise digitar pelo menos 1 caractere para mostrar as sugestões.

fhucho
fonte
Estou fazendo algo parecido AQUI !!! stackoverflow.com/questions/12854336/...
toobsco42

Respostas:

159

Este é um comportamento documentado :

Quando thresholdé menor ou igual a 0, um limite de 1 é aplicado.

Você pode mostrar manualmente o menu suspenso via showDropDown(), talvez seja possível organizá-lo quando quiser. Ou subclasse AutoCompleteTextViewe substituição enoughToFilter(), retornando o truetempo todo.

CommonsWare
fonte
7
O ShowDropDown () parecem funcionar bem em seting OnClickListener, mas coisa subclasse não está funcionando até que o usuário digitar uma letra e vem dels não back.But apenas com onClick ...
AMJ
9
Isso funciona perfeitamente em combinação com OnFocusChangeListener que chama showDropDown () quando a exibição ganha o foco.
Grishka 06/02
Também tenho que substituir o onFocusChanged, como indicado na resposta abaixo por @David Vávra
Gabriel
4
@commonsWare showDropDown()não está funcionando afterTextChangedquando .getText().toString().length()==0. WHYYY
Prabs
1
Substituir apenas o suficienteToFilter me ajuda. Obrigado!
Fedir Tsapana
121

Aqui está minha classe InstantAutoComplete . É algo entre AutoCompleteTextViewe Spinner.

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);
        }
    }

}

Use-o no seu xml assim:

<your.namespace.InstantAutoComplete ... />
David Vávra
fonte
12
Isso é ótimo! Eu também gostaria de salientar que no seu arquivo XML layout que você tem que mudar <AutoCompleteTextView ... />para <your.namespace.InstantAutoComplete ... />. Perdi algum tempo descobrir isso :)
Jules Colle
3
Ótima sugestão de classe: no método onFocusChanged, altere "se (focado)" para "se (focado && getAdapter ()! = Nulo)".
Jacob Tabak
Para AndroidX , estenda androidx.appcompat.widget.AppCompatAutoCompleteTextView.
Mahmudul Hasan Shohag
Isso não mostra o menu suspenso nas alterações de orientação.
Miha_x64 24/06
45

Caminho mais fácil:

Basta usar setOnTouchListener e showDropDown ()

AutoCompleteTextView text;
.....
.....
text.setOnTouchListener(new View.OnTouchListener(){
   @Override
   public boolean onTouch(View v, MotionEvent event){
      text.showDropDown();
      return false;
   }
});
user1913469
fonte
Para tornar isso ainda melhor, use if (! Text.isPopupShowing ()) {text.showDropDown (); }
Boldijar Paul 15/12/14
7
não é muito comum, mas isso não funcionará caso o usuário não toque para acessar este EditText. Por exemplo, ao usar um controle remoto com botões (Android TV, por exemplo).
desenvolvedor android
2
Você deve usar setOnFocusChanged. Alguém pode ter teclado e pressionar o botão TAB ou o uso do mouse e do touch list não será chamado.
Barwnikk
onTouchListener será chamado em horários diferentes para um único toque - Ex: o evento pode ser MotionEvent.ACTION_DOWN, MotionEvent.ACTION_UP. Portanto, é melhor verificar se há um evento específico e escrever o código
Govind
18

O código do Destil funciona muito bem quando há apenas um InstantAutoCompleteobjeto. Mas não funcionou com dois - não faço ideia do porquê. Mas quando eu coloco showDropDown()(como o CommonsWare recomendou) o onFocusChanged()seguinte:

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

resolveu o problema.

São apenas as duas respostas combinadas adequadamente, mas espero que isso possa poupar alguém algum tempo.

alex
fonte
2
Sua adição ajudou, mas ocorreu um erro se houvesse texto no InstantAutoComplete e a orientação da tela fosse alterada. Corrigi
FuryComputers
9

O adaptador não executa a filtragem inicialmente.
Quando a filtragem não é realizada, a lista suspensa fica vazia.
então você pode ter que iniciar a filtragem inicialmente.

Para fazer isso, você pode chamar filter()depois de terminar de adicionar as entradas:

adapter.add("a1");
adapter.add("a2");
adapter.add("a3");
adapter.getFilter().filter(null);
david m lee
fonte
6

Você pode usar onFocusChangeListener;

TCKimlikNo.setOnFocusChangeListener(new OnFocusChangeListener() {

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

            }

        }
    });
Göksel Güren
fonte
6

A resposta do Destil acima quase funciona, mas tem um bug sutil. Quando o usuário focaliza o campo pela primeira vez, no entanto, se ele sair e depois retornar ao campo, ele não mostrará a lista suspensa porque o valor de mPopupCanBeUpdated ainda será falso quando oculto. A correção é alterar o método onFocusChanged para:

@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("");
        }
    }
}
Colin Stewart
fonte
mas isso também significa que o texto será redefinido (apesar de tudo bem, normalmente) ...
desenvolvedor Android
3

Para criar CustomAutoCompleteTextView. 1. substitua o método 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; 
    } 
}
sanjeev vishnoi
fonte
3

tente

    searchAutoComplete.setThreshold(0);
    searchAutoComplete.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                }

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {//cut last probel
                    if (charSequence.length() > 1) {
                        if (charSequence.charAt(charSequence.length() - 1) == ' ') {
                            searchAutoComplete.setText(charSequence.subSequence(0, charSequence.length() - 1));
                            searchAutoComplete.setSelection(charSequence.length() - 1);
                        }
                    }
                   }


                @Override
                public void afterTextChanged(Editable editable) {
                }
            });


    //when clicked in autocomplete text view
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
              case R.id.header_search_etv:
                    if (searchAutoComplete.getText().toString().length() == 0) {
                        searchAutoComplete.setText(" ");
                    }
             break;
            }
        }):
Rafayel Pogosyan
fonte
3

Basta chamar esse método ao tocar ou clicar no evento do autoCompleteTextView ou onde desejar.

autoCompleteTextView.showDropDown()
Dalvinder Singh
fonte
0

Isso funcionou para mim, pseudo-código:

    public class CustomAutoCompleteTextView extends AutoCompleteTextView {
    public CustomAutoCompleteTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        this.showDropDown();
        return super.onTouchEvent(event);
    }
}

Nasif Md. Tanjim
fonte
0

Basta colar isso no seu método onCreate em Java

final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(
            this, android.R.layout.simple_spinner_dropdown_item,
            getResources().getStringArray(R.array.Loc_names));

    textView1 =(AutoCompleteTextView) findViewById(R.id.acT1);
    textView1.setAdapter(arrayAdapter);

    textView1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(final View arg0) {
            textView1.setMaxLines(5);
            textView1.showDropDown();

        }
    });

E isso no seu arquivo XML ...

<AutoCompleteTextView
            android:layout_width="200dp"
            android:layout_height="30dp"
            android:hint="@string/select_location"
            android:id="@+id/acT1"
            android:textAlignment="center"/>

E crie uma matriz em string.xml em Valores ...

<string-array name="Loc_names">

        <item>Pakistan</item>
        <item>Germany</item>
        <item>Russia/NCR</item>
        <item>China</item>
        <item>India</item>
        <item>Sweden</item>
        <item>Australia</item>
    </string-array>

E você está pronto para ir.

Lalit Fauzdar
fonte
0

Sete anos depois, pessoal, o problema permanece o mesmo. Aqui está uma classe com uma função que força esse pop-up estúpido a se mostrar em qualquer condição. Tudo o que você precisa fazer é definir um adaptador para o AutoCompleteTextView, adicionar alguns dados nele e chamar a showDropdownNow()função a qualquer momento.

Créditos para @David Vávra. É baseado no código dele.

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)
        }
    }
}
mykolaj
fonte
0

no FocusChangeListener, verifique

if (hasFocus) {
            tvAutoComplete.setText(" ")

no seu filtro, apenas apare este valor:

filter { it.contains(constraint.trim(), true) }

e mostrará todas as sugestões quando você se concentrar nessa visualização.

beokh
fonte