web-dev-qa-db-fra.com

Android: empêcher l'utilisateur de sélectionner autre que des suggestions de saisie semi-automatique?

J'ai fourni un AutoCompleteTextView pour montrer des suggestions à l'utilisateur. Sur la base de l'élément sélectionné par l'utilisateur, j'obtiens l'ID de l'élément et je l'utilise côté base de données. Maintenant, mon problème est de forcer l'utilisateur à faire une sélection uniquement à partir de AutoCompleteTextView (c'est-à-dire que l'utilisateur ne doit pas entrer son propre texte). C'est une exigence du client. Comment faire ça?

28
Prabhu M

Voici une solution assez simple:

Vous pouvez créer une variable pour stocker la valeur sélectionnée en définissant setOnItemClickListener dans votre AutoCompleteTextView. Ensuite, vous pouvez null cette valeur chaque fois qu'un utilisateur tape dans le champ en lui ajoutant un TextWatcher. Enfin, vous pouvez valider que votre variable n'est pas nulle avant de continuer.

String my_var; //keep track!
AutoCompleteTextView tv = (AutoCompleteTextView) layout.findViewById(R.id.tv);
tv.setAdapter(my_adapter);  
tv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        my_var = my_adapter.getItem(position).toString();
    }
});
/**
 * Unset the var whenever the user types. Validation will
 * then fail. This is how we enforce selecting from the list.
 */
tv.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        my_var = null;
    }
    @Override
    public void afterTextChanged(Editable s) {}
});
28
rmirabelle

Il se trouve que j'avais besoin d'une telle exigence pour un projet sur lequel je travaille, et je pense que je vais vous partager la façon dont j'ai mis en œuvre le nécessaire.

J'ai ajouté un écouteur de changement de focus pour la vue de texte à saisie automatique et vérifié quand l'utilisateur a le focus changé de focus à partir de la saisie automatique, et géré la situation directement.

autoTextViewCountry.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View view, boolean b) {
            if(!b) {
                // on focus off
                String str = autoTextViewCountry.getText().toString();

                ListAdapter listAdapter = autoTextViewCountry.getAdapter();
                for(int i = 0; i < listAdapter.getCount(); i++) {
                    String temp = listAdapter.getItem(i).toString();
                    if(str.compareTo(temp) == 0) {
                        return;
                    }
                }

                autoTextViewCountry.setText("");

            }
        }
    });

Donc, mon implémentation est la suivante: si le texte tapé n'existe pas dans l'adaptateur de tableau, le focus a changé de vide la vue de texte, et plus tard lors de la poursuite de l'étape suivante de l'enregistrement, vérifiez si cette vue de texte est vide ou non.

J'espère que cette approche aide quelqu'un.

Codage heureux.

17
NaseemH

NiceAutoCompleteTextView vous donnera la possibilité de vérifier si une sélection a été faite à partir de la liste déroulante, en appelant isSelectionFromPopup()

3
Rany Albeg Wein

Ok, je suppose que vous souhaitez limiter la saisie de l'utilisateur aux textes contenus dans la liste des éléments répertoriés dans la zone de suggestion.

Par exemple, si vous avez:

  • Une
  • Deux
  • Trois

alors l'utilisateur ne pouvait taper que le premier caractère "O" et "T". Et ainsi de suite selon le texte saisi précédemment.

Pour ce faire, vous pouvez utiliser la méthode setFilters de TextView :

editBox = (TextView) findViewById(R.id.editBox);
editBox.setFilters(getFilters());
editBox.addTextChangedListener(this);
editBox.setOnFocusChangeListener(this);

De plus, vous auriez probablement besoin du écouteur de changement de texte et écouteur de focus pour réagir et mettre à jour la liste filtrée lorsqu'un nouveau caractère est entré ... plus pour mettre à jour le filtre.

Voici un exemple de filtre de nombre décimal que j'ai utilisé sur un projet:

protected InputFilter[] getFilters()
    {
        InputFilter[] filters = new InputFilter[1];

        filters[0] = new InputFilter()
        {
            public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
            {
                // limit input to digits and decimal / thousand separator only
                // in case thousand separator is pressed, change it to decimal
                // separator instead
                String output = "";

                if (number.isFocused())
                {
                    for (int i = start; i < end; i++)
                    {
                        char c = source.charAt(i);

                        if (isDecimalOrThousandSeparator(c))
                        {
                            output = output + Character.toString(decimalSeparator);
                        }
                        else if (Character.isDigit(c))
                        {
                            output = output + Character.toString(c);
                        }
                    }

                    return output == "" ? null : output;
                }

                return null;
            }
        };

        return filters;
    }
1
Drejc

Une solution simple serait de simplement vérifier si l'entrée actuelle est l'un des éléments de l'adaptateur. Vous pouvez le faire comme ceci:

val AutoCompleteTextView.isValid: Boolean
    get() {
        for (i in 0 until adapter.count) {
            if (adapter.getItem(i) == text.toString()) {
                return true
            }
        }

        return false
    }
0
Max