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?
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) {}
});
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.
NiceAutoCompleteTextView vous donnera la possibilité de vérifier si une sélection a été faite à partir de la liste déroulante, en appelant isSelectionFromPopup()
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:
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;
}
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
}