Two-Way Data Binding Conversions

I’ve seen a few questions regarding using Android Data Binding with EditText, but with a different type. For example, you may want the EditText to bind to an integer value:

<EditText android:text="@={user.age}" ../>

or float value:

<EditText android:text="@={user.favoriteRationalNumber}" ../>

or maybe even a custom object.

With Android Studio 2.2’s gradle plugin, you can use a simplified conversion form:

<EditText android:text="@={`` + user.age}" ../>

This converts to and from a String from any primitive type.

However, this doesn’t work on Android Studio 2.1, nor does it work for any custom type, so you must implement it yourself. Here’s how you can do it for a float value:

@BindingAdapter("android:text")
public static void setText(TextView view, float value) {
    boolean setValue = view.getText().length() == 0;
    try {
        if (!setValue) {
            setValue = Float.parseFloat(view.getText().toString()) != value;
        }
    } catch (NumberFormatException e) {
    }
    if (setValue) {
        view.setText(String.valueOf(value));
    }
}

@InverseBindingAdapter(attribute = "android:text")
public static float getText(TextView view) {
    try {
        return Float.parseFloat(view.getText().toString());
    } catch (NumberFormatException e) {
        return 0;
    }
}

In this, you’ll have¬†erroneous float format for text return 0. You may want to keep track of the old value and return it if there is an error. If you do, remember to use a weak reference, such as a WeakHashMap so that you don’t end up leaking View references everywhere.

Advertisements

4 thoughts on “Two-Way Data Binding Conversions

  1. I am getting ****/ data binding error ****msg:Could not find event ‘textAttrChanged’ on View type ‘android.support.design.widget.TextInputEditText’ on Android 2.1. I had to add textChanged listener like below to make it to work.

    @BindingAdapter(value = {“onTextChange”, “textAttrChanged”}, requireAll = false)
    public static void setTextListener(TextView view,
    final TextWatcher listener,
    final InverseBindingListener textChange) {
    if (textChange == null) {
    view.addTextChangedListener(listener);
    } else {
    view.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) {
    if (listener != null){
    listener.onTextChanged(s, start, before, count);
    }
    else {
    textChange.onChange();
    }
    }

    @Override
    public void afterTextChanged(Editable s) {}
    });
    }
    }

    Thank You

    • There was a bug that required this, but it has been fixed. I believe that the latest version of Android Grade Plugin 2.2 should have the fix. Of course, if you don’t have an observable, you won’t get updates from the model, but you may not care about that.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s