Android: AutoCompleteTextView muestra sugerencias cuando no se ingresa texto

127

Estoy usando AutoCompleteTextView, cuando el usuario hace clic en él, quiero mostrar sugerencias incluso si no tiene texto, pero setThreshold(0)funciona exactamente igual que setThreshold(1), por lo que el usuario debe ingresar al menos 1 carácter para mostrar las sugerencias.

fhucho
fuente
¡Estoy haciendo algo similar AQUÍ! stackoverflow.com/questions/12854336/…
toobsco42

Respuestas:

159

Este es un comportamiento documentado :

Cuando thresholdes menor o igual a 0, se aplica un umbral de 1.

Puede mostrar manualmente el menú desplegable a través de showDropDown(), por lo que tal vez pueda hacer arreglos para mostrarlo cuando lo desee. O, subclase AutoCompleteTextViewy anulación enoughToFilter(), regresando truetodo el tiempo.

CommonsWare
fuente
77
El showDropDown () parece funcionar bien en proponiéndose OnClickListener, pero lo subclase no funciona hasta que el usuario introduzca una letra y viene dels back.But no solo con onClick ...
AMJ
9
Esto funciona perfectamente en combinación con OnFocusChangeListener que llama a showDropDown () cuando la vista gana el foco.
Grishka
También tengo que anular el onFocusChanged, como se indica en la respuesta a continuación por @David Vávra
Gabriel
44
@commonsWare showDropDown()no funciona afterTextChangedcuando .getText().toString().length()==0. WHYYY
Prabs
1
Solo anular lo suficiente ToFilter me ayuda. ¡Gracias!
Fedir Tsapana
121

Aquí está mi clase InstantAutoComplete . Es algo entre AutoCompleteTextViewy 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);
        }
    }

}

Úselo en su xml así:

<your.namespace.InstantAutoComplete ... />
David Vávra
fuente
12
¡Eso es genial! También me gustaría señalar que en el archivo XML diseño tiene que cambiar <AutoCompleteTextView ... />a <your.namespace.InstantAutoComplete ... />. Perdí algo de tiempo resolviendo esto :)
Jules Colle
3
Gran sugerencia de clase solamente estaría en el método onFocusChanged, cambie el "if (centrado)" a "if (centrado && getAdapter ()! = Null)".
Jacob Tabak
Para AndroidX , extienda androidx.appcompat.widget.AppCompatAutoCompleteTextView.
Mahmudul Hasan Shohag
Esto no muestra el menú desplegable sobre los cambios de orientación.
Miha_x64
45

La manera más fácil:

Simplemente use setOnTouchListener y showDropDown ()

AutoCompleteTextView text;
.....
.....
text.setOnTouchListener(new View.OnTouchListener(){
   @Override
   public boolean onTouch(View v, MotionEvent event){
      text.showDropDown();
      return false;
   }
});
usuario1913469
fuente
Para hacerlo aún mejor, use if (! Text.isPopupShowing ()) {text.showDropDown (); }
Boldijar Paul
77
no es muy común, pero esto no funcionará en caso de que el usuario no toque para ir a este EditText. Por ejemplo, cuando se usa un control remoto con botones (Android TV, por ejemplo).
Desarrollador de Android
2
Debe usar setOnFocusChanged. Alguien puede tener el teclado y presionar el botón TAB o usar el mouse y tocar el oyente no será llamado
barwnikk
onTouchListener recibirá llamadas en diferentes momentos para un solo toque - Ej: el evento puede ser MotionEvent.ACTION_DOWN, MotionEvent.ACTION_UP. Por lo tanto, es mejor verificar un evento específico y escribir el código
Govind
18

El código de Destil funciona muy bien cuando solo hay un InstantAutoCompleteobjeto. Sin embargo, no funcionó con dos , ni idea de por qué. Pero cuando pongo showDropDown()(como recomienda CommonsWare) en onFocusChanged()esto:

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

Se solucionó el problema.

Son solo las dos respuestas combinadas correctamente, pero espero que le ahorre algo de tiempo a alguien.

alex
fuente
2
Su adición ayudó, pero recibí un error si había texto en InstantAutoComplete y la orientación de la pantalla cambiaba. Lo arreglé marcando
FuryComputers
9

El adaptador no realiza el filtrado inicialmente.
Cuando no se realiza el filtrado, la lista desplegable está vacía.
por lo que es posible que deba comenzar el filtrado inicialmente.

Para hacerlo, puede invocar filter()después de terminar de agregar las entradas:

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

Puede usar onFocusChangeListener;

TCKimlikNo.setOnFocusChangeListener(new OnFocusChangeListener() {

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

            }

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

La respuesta anterior de Destil casi funciona, pero tiene un error sutil. Cuando el usuario enfoca el campo por primera vez, funciona, sin embargo, si se va y luego regresa al campo, no mostrará el menú desplegable porque el valor de mPopupCanBeUpdated seguirá siendo falso cuando estaba oculto. La solución es cambiar el método onFocusChanged a:

@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
fuente
pero esto también significa que el texto se restablecerá (aunque generalmente está bastante bien) ...
desarrollador de Android
3

Para hacer CustomAutoCompleteTextView. 1. anular setThreshold, enoughToFilter, método 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
fuente
3

intentalo

    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
fuente
3

Simplemente llame a este método en el evento táctil o haga clic en autoCompleteTextView o donde desee.

autoCompleteTextView.showDropDown()
Dalvinder Singh
fuente
0

Esto funcionó para mí, pseudocó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
fuente
0

Simplemente pegue esto en su método onCreate en 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();

        }
    });

Y esto a su archivo Xml ...

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

Y cree una matriz en string.xml en 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>

Y eres bueno para ir.

Lalit Fauzdar
fuente
0

Siete años después, chicos, el problema sigue siendo el mismo. Aquí hay una clase con una función que obliga a esa estúpida ventana emergente a mostrarse en cualquier condición. Todo lo que necesita hacer es configurar un adaptador para su AutoCompleteTextView, agregar algunos datos y llamarshowDropdownNow() función en cualquier momento.

Créditos a @David Vávra. Está basado en su código.

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
fuente
0

en FocusChangeListener, verifique

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

en su filtro, simplemente recorte este valor:

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

y mostrará todas las sugerencias cuando te concentres en esta vista.

beokh
fuente