There is no simple solution to this. But, I went ahead and created a kind of changes which almost work like a 2-way binding.
My EditText was looking like this:
<EditText
android:id="@+id/amount"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.1"
android:digits="0123456789."
android:gravity="end"
android:inputType="numberDecimal|numberSigned"
android:onTextChanged="@{() -> handler.valueAmountChanged(amount)}"
android:selectAllOnFocus="true"
android:text="0"
android:textColor="@color/selector_disabled_edit_text"
app:userVal="@{userAmount}" />
handler
is the instance of the activity. And it contains the valueAmountChanged(EditText editText)
method.
Now in your value amount checked, I am parsing that text string and storing it in the respective variable.
For me, it is looking something like this:
public void valueAmountChanged(EditText editText) {
double d = 0.0;
try {
String currentString = editText.getText().toString();
// Remove the 2nd dot if present
if (currentString.indexOf(".", currentString.indexOf(".") + 1) > 0)
editText.getText().delete(editText.getSelectionStart() - 1, editText.getSelectionEnd());
// Remove extra character after 2 decimal places
currentString = editText.getText().toString(); // get updated string
if (currentString.matches(".*\\.[0-9]{3}")) {
editText.getText().delete(currentString.indexOf(".") + 3, editText.length());
}
d = Double.valueOf(editText.getText().toString());
} catch (NumberFormatException e) {
}
userAmount = d; // this variable is set for binding
}
Now, as we change the userAmount
variable it will going to reflect as we have set the binding adapter with app:userVal
argument in the EditText
.
So, with binding adapter we check if the new value is not the current value, then update the value. Else, leave it as it is. We need to do this, because if user is typing and binding adapter updates the value, then it will loose is cursor position and will bring it to the front. So, this will save us from that.
@BindingAdapter({"userVal"})
public static void setVal(EditText editText, double newVal) {
String currentValue = editText.getText().toString();
try {
if (Double.valueOf(currentValue) != newVal) {
DecimalFormat decimalFormat = new DecimalFormat("#.##");
String val = decimalFormat.format(newVal);
editText.setText(val);
}
} catch (NumberFormatException exception) {
// Do nothing
}
}
This is a bit typical approach, I know. But, couldn't find any better than this. There is also very less documentation available and others are in the form of blog posts on medium, which should have been added to the official documentation.
Hope it helps someone.