web-dev-qa-db-fra.com

Comment faire un lien vers onTextChanged pour un EditText sur Android?

Dans Les propos de Yigit Boyar et George Mount sur la liaison de données Android illustrent à quel point il est facile de se lier à TextWatcher's onTextChanged (à 13h41). Sur un bouton. Sont leurs diapositives mal? Tout d’abord, la vue Button ne possède pas de propriété onTextChanged. Il n'a pas non plus de méthode setOnTextChanged. EditText non plus. Mais ils ont tous les deux addTextChangedListener qui prend un TextWatcher en entrée.

Alors de quoi parlent-ils? Comment font-ils? Leur exemple de code ne compile pas, mais donne cette erreur:

Error:(17) No resource identifier found for attribute 'onTextChanged' in package 'Android'

Comment puis-je me lier à un "événement de texte modifié" sur n'importe quelle vue, ou en particulier EditText, avec le cadre de liaison de données Android?

16
Nilzor

En fait, cela fonctionne hors de la boîte. Je pense que mon erreur a été d'utiliser une ancienne version du framework de liaison de données. En utilisant les dernières, voici la procédure:

Vue:

<EditText
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:id="@+id/username"
    Android:text="Enter username:"
    Android:onTextChanged="@{data.onTextChanged}" />

Modèle:

public void onTextChanged(CharSequence s, int start, int before, int count) {
    Log.w("tag", "onTextChanged " + s);
}

Assurez-vous de bien référencer les outils de génération Gradle v1.5.0 ou supérieurs et d'avoir activé la liaison de données avec Android.dataBinding.enabled true dans votre build.gradle.

edit: Projet de démonstration fonctionnel ici . vue . modèle .

53
Nilzor

Pour étendre la réponse @Nilzors, il est également possible de passer du texte et/ou d’autres paramètres dans la présentation:

Vue:

<EditText
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:id="@+id/username"
    Android:text="Enter username:"
    Android:onTextChanged="@{(text, start, before, count) -> viewModel.onUsernameTextChanged(text)}" />

ViewModel:

public void onUsernameTextChanged(CharSequence text) {
    // TODO do something with text
}

Vous devez toujours transmettre zéro ou tous les paramètres.

23
Micer

Meilleure et facile approche

Si vous utilisez onTextChange() pour avoir le texte mis à jour dans le modèle, vous pouvez directement utiliser Liaison à deux voies .

<data>
    <variable
        name="user"
        type="com.package.User"/>
</data>

<EditText
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="@={user.name}"/>

Et votre classe de modèles aura getter & setter.

public class User {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Maintenant, le nom dans le modèle sera modifié en temps réel avec l'interaction de l'utilisateur. Ainsi, chaque fois que vous utiliserez binding.getUser().getName(), vous obtiendrez le dernier texte.

One-Way Binding ne sera mis à jour que lorsque la valeur du modèle aura été modifiée. Il ne met pas à jour le modèle en temps réel.

Android:text="@{user.name}"

Liaison bidirectionnelle met à jour la variable de modèle en temps réel avec la saisie de l'utilisateur. 

Android:text="@={user.name}"

La SEULE différence est de = (signe égal) dans les reliures unidirectionnelle et bidirectionnelle.

1
Khemraj