2

I am using Binding adapter to prevent constant text update of edittexts for 2 way binding.

@BindingAdapter("binding")
public static void bindEditText(EditText editText, final String str) {
    if ((!editText.getText().toString().equals(str)) && !editText.getText().equals("")) {
        editText.setText(str);
    }
}

It works fine with edit text with integer default text. But when it comes to edit text with float default text. Ex: 70.0, when I key in the first digit, the edit text refreshes and became Ex: 8.0. The cursor then move to left and all the following digits will be added to the front. Ex: 198.0

Tried this, but doesn't work.

@BindingAdapter("binding")
public static void bindEditText(EditText editText, final String str) {
    if ((!(editText.getText().toString()+".0").equals(str)) && !editText.getText().equals("")) {
            editText.setText(str);
    }
}

Any solution?

Alex
  • 881
  • 2
  • 10
  • 24

1 Answers1

5

I'm not sure everyone knows: Android Data Binding now supports two-way binding. You need Android Studio 2.1 and then you can bind your field as two-way using an extra '=' character:

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

You won't need any additional Binding Adapter.

https://halfthought.wordpress.com/2016/03/23/2-way-data-binding-on-android/

That said, you're assigning a float to a String field. With the Android Studio 2.2 gradle plugin, you'll be able to use a shortcut for this that allows two-way binding with primitive conversions:

<EditText android:text="@={`` + data.floatNumber}" .../>

But with Android Studio 2.1, you'll have to do your own conversions Binding Adapters. This one lets the user edit the field and only accepts a valid float:

@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;
    }
}
George Mount
  • 20,708
  • 2
  • 73
  • 61
  • Thanks for your help! Actually, in the edit text box, I have concatenated float with a string, @={data.floatnumber + someString}, it gives me the error cannot be inverted: String concatenation operator (+) is not supported in two-way binding. How can I deal with this situation? I must use binding adapter now? – Alex May 27 '16 at 06:19
  • @BindingAdapter("android:text") is modifying the behavior of android:text? Will this affect every views that uses android:text? – Alex May 27 '16 at 06:27
  • You'll have to do your own inversion logic to strip away the extra string if you want that. There's no meaningful way to do that with a single BindingAdapter. – George Mount May 27 '16 at 17:15
  • 1
    Yes, this BindingAdapter will modify the behavior for android:text in that it will work with all float values. If you are binding to strings as usual, it won't affect that at all. If you want to have per-View binding logic, you'll have to use a different attribute on each View so that a different method is called. You'll also have to create a BindingAdapter for the event attribute. You can look at the source for `TextViewBindingAdapter.setTextWatcher` to see how it is done there, but you should be able to simplify it if you don't have your own `onTextChanged` listeners. – George Mount May 27 '16 at 17:20
  • Fairly straight forward! Thanks a lot for your help and reply! – Alex May 27 '16 at 17:47