1

I have this adapters in a Binding Utils class:

@BindingAdapter("text")
public static void bindDoubleInText(AppCompatEditText tv, Double 
value)
{
    if (tv.getText() == null) return;

    // Get the actual EditText value
    String edittextValue = tv.getText().toString();

    if (edittextValue.isEmpty())
    {
        if (value != null) tv.setText(Double.toString(value));
    }
    else
    {
        if (value != null && 
Double.parseDouble(tv.getText().toString()) != value)
            tv.setText(Double.toString(value));
    }
}

@InverseBindingAdapter(attribute = "android:text")
public static Double getDoubleFromBinding(TextView view)
{
    String string = view.getText().toString();

    return string.isEmpty() ? null : Double.parseDouble(string);
}

@BindingAdapter("text")
public static void bindIntegerInText(AppCompatEditText 
appCompatEditText, Integer value)
{
    CharSequence charSequence = appCompatEditText.getText();

    if (charSequence == null || value == null) return;

    // Get the actual EditText value
    String edittextValue = charSequence.toString();

    if (edittextValue.isEmpty() || Integer.parseInt(edittextValue) != 
value)
        appCompatEditText.setText(Integer.toString(value));
}

@InverseBindingAdapter(attribute = "android:text")
public static Integer getIntegerFromBinding(TextView view)
{
    String string = view.getText().toString();

    return string.isEmpty() ? null : Integer.parseInt(string);
}`

And this is part of one of my xml files:

<android.support.v7.widget.AppCompatEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:gravity="center_horizontal"
android:hint="dosis"
android:inputType="numberDecimal"
android:minEms="5"
android:text="@={workOrderFertilizer.dose}"/>`

The thing is that in Android Studio 2.2.3 version is working great. When I updated to Android Studio 2.3 this stopped working and Gradle shows multiple errors. I have changed the attribute of the Binding adapters and Inverse binding adapters from "android:text" to "text" but it's not working. Something similar happened to another user in this question: Data Binding broke after upgrade to Gradle 2.3 but the difference is that I'm using "android:text" for the binding so the answer given by George Mount is no working for me. Anybody has any ideas? I'm really frustrated with this because I can't update Android Studio because of this problem.

Dan Ponce
  • 636
  • 1
  • 8
  • 24
  • Could it be that your BindingAdapter is using "text" and not "android:text"? – George Mount Jul 30 '17 at 23:34
  • When I use Android studio 2.2.3 and using android:text in binding and inverse binding adapters it shows no errors but in version 2.3 and above it shows the error that the getter and setter aren't found ( Double or Integer) – Dan Ponce Jul 31 '17 at 00:46
  • Thanks @GeorgeMount for answering. So that you know I have tried also with android:text=" `` + object.double" and it shows no error in Android Studio 2.3 and above but the two way binding is not working as it should – Dan Ponce Jul 31 '17 at 01:49
  • Two way binding should still work. I forget now when `'@={"" + object.double}` was introduced. There were some changes to how ObservableField was handled in 2.3. Have you tried 3.0 to see if it works there. Just wondering if it is a bug that was fixed or if we changed something purposely. – George Mount Jul 31 '17 at 05:34
  • Thanks @GeorgeMount I just finished a basic app that shows two way binding does not work using the example of yours (using Android Studio 3.0) : https://github.com/danponce/bindtest – Dan Ponce Jul 31 '17 at 15:44
  • Those shortcuts only work with primitives. I'll give an answer so that I can type some code. – George Mount Jul 31 '17 at 18:20
  • Thanks @GeorgeMount for the help! I need to make two way binding using wrapers (Double, Integer, etc). Do you know how can I get my adapters to work with new Android Studio versions? That would be a really great help! – Dan Ponce Jul 31 '17 at 18:25

2 Answers2

2

The shortcuts for two-way binding such as android:text='@={"" + obj.val}' only work with primitives and not with their Object wrappers like Double and Float.

You can make two-way binding work with the wrappers with BindingAdapters. I wrote these and they seem to work alright:

@BindingAdapter("android:text")
public static void setDouble(TextView view, Double val) {
    if (val != null) {
        String currentValue = view.getText().toString();
        if (currentValue.length() != 0) {
            try {
                double oldVal = Double.parseDouble(currentValue);
                if (oldVal == val) {
                    return;
                }
            } catch (NumberFormatException e) {
                // that's ok, we can just set the value.
            }
        }
        view.setText(val.toString());
    }
}

@InverseBindingAdapter(attribute = "android:text")
public static Double getDouble(TextView view) {
    try {
        return Double.parseDouble(view.getText().toString());
    } catch (NumberFormatException e) {
        return null;
    }
}

With Android gradle plugin 3.0, you can also use conversion functions, but the input goes a little wonky unless you do some management. You can bind it like this:

<EditText
    android:id="@+id/textView"
    android:text="@={Converters.doubleToString(textView, item.dose)}" .../>

and have converters like this:

@InverseMethod("doubleToString")
public static Double stringToDouble(TextView view, CharSequence value) {
    if (value == null) {
        return null;
    }
    try {
        return Double.parseDouble(value.toString());
    } catch (NumberFormatException e) {
        return null;
    }
}

public static CharSequence doubleToString(TextView view, Double value) {
    if (value == null) {
        return "";
    }
    String oldText = view.getText().toString();
    if (!oldText.isEmpty()) {
        try {
            double oldVal = Double.parseDouble(oldText);
            if (oldVal == value) {
                return view.getText();
            }
        } catch (NumberFormatException e) {
            // No problem. The TextView had text that wasn't formatted properly
        }
    }
    return value.toString();
}
George Mount
  • 20,708
  • 2
  • 73
  • 61
  • Thanks for the answer! I'll try with the binding adapters and I'll let you know if it works – Dan Ponce Jul 31 '17 at 19:22
  • In this case which are the advantages for implementing the converters? and how are they imported to the xml layout? – Dan Ponce Jul 31 '17 at 21:57
  • No advantage. Better to use the Binding Adapters in this case. – George Mount Aug 01 '17 at 04:40
  • I just updated the GitHub repository ( github.com/danponce/bindtest ) and added new methods for converting Integer values and they're throwing the error that I was talking about: "error: incompatible types: Integer cannot be converted to Double" Can you help me please. I'm really frustrated with this error. I can't update my Android Studio because of this @GeorgeMount – Dan Ponce Aug 29 '17 at 14:51
  • You've discovered a bug. I'll file it. I'm hoping that I can get the fix in for 3.0, but the team is unlikely to take a fix so late. Until then, maybe you can use the conversions? – George Mount Aug 29 '17 at 20:29
  • I added the Converter class but is throwing me this error: "Error:cannot generate view binders java.lang.ClassCastException: android.databinding.tool.expr.IdentifierExpr cannot be cast to android.databinding.tool.expr.StaticIdentifierExpr". Check my updated repository please @GeorgeMount – Dan Ponce Aug 30 '17 at 14:40
  • You should use `import` instead of `variable` for your Converter class in the `data` section. – George Mount Aug 30 '17 at 19:41
  • I realized that in the new Android Studio version (3.0) the fix wasn't added. Do you know when it's going to be added? – Dan Ponce Oct 30 '17 at 03:53
0

you have to like something below

<android.support.v7.widget.AppCompatEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:gravity="center_horizontal"
android:hint="dosis"
android:inputType="numberDecimal"
android:minEms="5"
android:setText="@{workOrderFertilizer.dose}"/>

in Adapter

@BindingAdapter("setText")
public static void bindDoubleInText(AppCompatEditText tv, Object
d)
{
    Double value = (Double) d;
    if (tv.getText() == null) return;

    // Get the actual EditText value
    String edittextValue = tv.getText().toString();

    if (edittextValue.isEmpty())
    {
        if (value != null) tv.setText(Double.toString(value));
    }
    else
    {
        if (value != null && 
Double.parseDouble(tv.getText().toString()) != value)
            tv.setText(Double.toString(value));
    }
}
Mehul Kabaria
  • 6,404
  • 4
  • 25
  • 50