Android: AutoCompleteTextView affiche des suggestions lorsqu'aucun texte n'est entré


127

J'utilise AutoCompleteTextView, lorsque l'utilisateur clique dessus, je veux afficher des suggestions même s'il n'a pas de texte - mais setThreshold(0)fonctionne exactement de la même manière que setThreshold(1)- donc l'utilisateur doit entrer au moins 1 caractère pour afficher les suggestions.


Je fais quelque chose de similaire ICI !!! stackoverflow.com/questions/12854336/…
toobsco42

Réponses:


159

Il s'agit d' un comportement documenté :

Lorsque thresholdest inférieur ou égal à 0, un seuil de 1 est appliqué.

Vous pouvez afficher manuellement le menu déroulant via showDropDown(), vous pouvez donc peut-être vous arranger pour l'afficher quand vous le souhaitez. Ou, sous AutoCompleteTextView- classe et remplacement enoughToFilter(), en retournant truetout le temps.


7
Le showDropDown () semble bien fonctionner sur la configuration de onClickListener, mais la sous-classe ne fonctionne pas tant que l'utilisateur n'a pas saisi une lettre et revient dels.Mais pas seulement avec onClick ...
amj

9
Cela fonctionne parfaitement en combinaison avec OnFocusChangeListener qui appelle showDropDown () lorsque la vue obtient le focus.
Grishka

Je dois également remplacer le onFocusChanged, comme indiqué sur la réponse ci-dessous par @David Vávra
Gabriel

4
@commonsWare showDropDown()ne fonctionne pas afterTextChangedquand .getText().toString().length()==0. WHYYY
Prabs

1
Seul le dépassement de suffisammentToFilter m'aide. Je vous remercie!
Fedir Tsapana

121

Voici ma classe InstantAutoComplete . C'est quelque chose entre AutoCompleteTextViewet 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);
        }
    }

}

Utilisez-le dans votre xml comme ceci:

<your.namespace.InstantAutoComplete ... />

12
C'est génial! Je tiens également à souligner que dans votre fichier XML de mise en page, vous devez passer <AutoCompleteTextView ... />à <your.namespace.InstantAutoComplete ... />. J'ai perdu du temps à comprendre :)
Jules Colle

3
Excellente classe - seule la suggestion serait dans la méthode onFocusChanged, changez le "if (focus)" en "if (focus && getAdapter ()! = Null)".
Jacob Tabak

Pour AndroidX , étendezandroidx.appcompat.widget.AppCompatAutoCompleteTextView .
Mahmudul Hasan Shohag

Cela ne montre pas de liste déroulante sur les changements d'orientation.
Miha_x64 le

45

Moyen le plus simple:

Utilisez simplement setOnTouchListener et showDropDown ()

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

Pour rendre cela encore meilleur, utilisez if (! Text.isPopupShowing ()) {text.showDropDown (); }
Boldijar Paul

7
pas très courant, mais cela ne fonctionnera pas au cas où l'utilisateur ne toucherait pas pour accéder à cet EditText. Par exemple lors de l'utilisation d'une télécommande avec des boutons (Android TV, par exemple).
développeur android

2
Vous devez utiliser setOnFocusChanged. Quelqu'un peut avoir un clavier et appuyer sur le bouton TAB ou utiliser la souris et l'écouteur tactile ne sera pas appelé.
barwnikk

onTouchListener sera appelé à plusieurs reprises pour un seul tap - Ex: l'événement peut être MotionEvent.ACTION_DOWN, MotionEvent.ACTION_UP. Il est donc préférable de vérifier un événement spécifique et d'écrire le code
Govind

18

Le code de Destil fonctionne très bien lorsqu'il n'y a qu'un seul InstantAutoCompleteobjet. Cela n'a pas fonctionné avec deux - je ne sais pas pourquoi. Mais quand je mets showDropDown()(tout comme CommonsWare conseillé) dans onFocusChanged()comme ceci:

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

cela a résolu le problème.

Ce ne sont que les deux réponses correctement combinées, mais j'espère que cela permettra à quelqu'un de gagner du temps.


2
Votre ajout a aidé, mais j'ai eu une erreur s'il y avait du texte dans InstantAutoComplete et que l'orientation de l'écran avait changé. Je l'ai corrigé en vérifiant la visibilité de la fenêtre, j'ai posté le nouveau code ici: gist.github.com/furycomptuers/4961368
FuryComputers

9

L'adaptateur n'effectue pas de filtrage au départ.
Lorsque le filtrage n'est pas effectué, la liste déroulante est vide.
vous devrez peut-être commencer le filtrage.

Pour ce faire, vous pouvez appeler filter()après avoir terminé d'ajouter les entrées:

adapter.add("a1");
adapter.add("a2");
adapter.add("a3");
adapter.getFilter().filter(null);

6

Vous pouvez utiliser onFocusChangeListener;

TCKimlikNo.setOnFocusChangeListener(new OnFocusChangeListener() {

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

            }

        }
    });

6

La réponse de Destil ci-dessus fonctionne presque, mais a un bug subtil. Lorsque l'utilisateur donne le focus au champ pour la première fois, cela fonctionne, mais s'il quitte et retourne au champ, il n'affichera pas la liste déroulante car la valeur de mPopupCanBeUpdated sera toujours fausse à partir du moment où elle a été masquée. Le correctif consiste à changer la méthode onFocusChanged en:

@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("");
        }
    }
}

mais cela signifie aussi que le texte sera réinitialisé (bien que ce soit généralement correct) ...
développeur android

3

Pour créer CustomAutoCompleteTextView. 1. remplacer la méthode setThreshold, assezToFilter, 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; 
    } 
}

3

l'essayer

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

3

Appelez simplement cette méthode au toucher ou au clic de l'événement autoCompleteTextView ou à l'endroit souhaité.

autoCompleteTextView.showDropDown()

0

Cela a fonctionné pour moi, pseudo code:

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


0

Collez-le simplement dans votre méthode 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();

        }
    });

Et ceci dans votre fichier Xml ...

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

Et créez un tableau dans string.xml sous Values ​​...

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

Et vous êtes prêt à partir.


0

Sept ans plus tard, les gars, le problème reste le même. Voici une classe avec une fonction qui force ce pop-up stupide à se montrer dans toutes les conditions. Tout ce que vous avez à faire est de définir un adaptateur sur votre AutoCompleteTextView, d'y ajouter des données et d'appeler la showDropdownNow()fonction à tout moment.

Crédits à @David Vávra. C'est basé sur son code.

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

0

sur FocusChangeListener, vérifiez

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

dans votre filtre, coupez simplement cette valeur:

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

et il affichera toutes les suggestions lorsque vous vous concentrerez sur cette vue.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.