web-dev-qa-db-ja.com

AndroidのEditTextのonTextChangedにデータバインドする方法は?

Yigit BoyarとGeorge MountのAndroid Databinding でのトークでは、TextWatcheronTextChanged(13時) :41)。ボタン上。スライドは間違っていますか?まず、ButtonビューにはonTextChangedプロパティがありませんが、setOnTextChangedメソッドもありません。 EditTextを行いますが、両方ともaddTextChangedListenerを入力として取るTextWatcherを持っています。

彼らは何について話しているのですか?どうやってやっているの?サンプルコードはコンパイルされませんが、このエラーが発生します。

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

Android Databindingフレームワークを使用して、任意のビュー、または特にEditTextで「テキスト変更イベント」にバインドするにはどうすればよいですか?

28
Nilzor

実際には、すぐに使用できます。私の間違いは、データバインディングフレームワークの古いバージョンを使用していたと思います。最新を使用して、これは手順です:

表示:

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

モデル:

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

Gradleビルドツールv1.5.0以降を参照しており、Android.dataBinding.enabled trueはbuild.gradleにあります。

edit:機能デモプロジェクト ここviewモデル

67
Nilzor

@Nilzorsの答えを拡張するために、レイアウトでテキストやその他のパラメーターを渡すこともできます。

表示:

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

常にゼロまたはすべてのパラメーターを渡す必要があります。

36
Micer

簡単な方法

onTextChange()を使用して、モデル内の更新されたテキストを使用している場合は、直接 Two-way Binding を使用できます。 =。

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

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

また、モデルクラスにはgettersetterがあります。

_public class User {
    private String name;

    public String getName() {
        return name;
    }

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

これで、モデル内の名前は、ユーザーの操作によりリアルタイムに変更されます。したがって、binding.getUser().getName()を使用すると、常に最新のテキストが取得されます。

一方向バインディングは、モデル値が変更された場合にのみ更新されます。モデルをリアルタイムで更新しません。

_Android:text="@{user.name}"
_

Two-Way Bindingユーザー入力を使用してモデル変数をリアルタイムで更新します。

_Android:text="@={user.name}"
_

唯一の違いは_=_(等号)です プロパティへのデータ変更を受け取り、同時にユーザーの更新をリッスンしますtime

8
Khemraj

これに最適な方法は、バインドアダプターとテキストウォッチャーを追加することです。

public class Model{
    private TextWatcher textWatcher;

public Model(){
        this.textWatcher= getTextWatcherIns();
}

private TextWatcher getTextWatcherIns() {
        return new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                //do some thing
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                //do some thing

            }

            @Override
            public void afterTextChanged(Editable s) {
                //do some thing
            }
        };
    }

    public TextWatcher getTextWatcher() {
        return textWatcher;
    }

    public void setTextWatcher(TextWatcher textWatcher) {
        this.textWatcher = textWatcher;
    }

    @BindingAdapter("textChangedListener")
    public static void bindTextWatcher(EditText editText, TextWatcher textWatcher) {
        editText.addTextChangedListener(textWatcher);
    }
}

そして、あなたのXMLでこの属性を編集テキストに追加してください

<EditText
            Android:id="@+id/et"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            app:textChangedListener="@{model.textWatcher}" />
0
mahdi shahbazi