Two-way data binding with double value in EditText

In Android, we can use two-way data binding with @= in front of the variable. But this variable is equal to double . So to display it in EditText I need to convert it to String using String.valueOf(pojo.value) .

If I attach = forward to bind two-way data, it just doesn't compile.

If I attach onTextChanged and set the value there, I lose the cursor. Is there a workaround?

Edit:

It worked with the InverseBindingAdapter , but does not allow typing . (period).

+5
source share
2 answers

There is no easy solution. But I went ahead and created changes that almost work like two-way binding.

My EditText looked 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 an example of activity. And it contains the valueAmountChanged(EditText editText) method.

Now that you have checked the number of values, I parse this text string and save it in the appropriate variable.

For me it looks 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, when we change the userAmount variable, it will be displayed, since we installed the binding adapter with the app:userVal in EditText .

So, with the binding adapter, we check to see if the new value is the current value, and then update the value. Stay, leave it as it is. We must do this, because if the user prints and binds the adapter updates, then he will lose the cursor position and bring it to the fore. Thus, it will save us from this.

 @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 slightly typical approach, I know. But could not find anything better than this. There is also very little documentation, while others are in the form of blog posts on media that should be added to the official documentation.

Hope this helps someone.

+1
source

Your solution worked partially for me. I used @BindingAdaptor, and the value of the "Amount" variable was reflected in the text of the edit, but OnTextChangeListner did not start when the value changed. So I used TextWatcher in VM. Here is the code for VM and XML. Nothing should be written in action.

 //VIEW MODEL @SerializedName("Amount") private Double Amount ; @Bindable public Double getAmount() { return (Amount == null)? 0.0 : Amount; } public void setAmount(Double amount) { Amount = amount; notifyPropertyChanged(BR.amount); } public TextWatcher getAmountWatcher() { return new SimpleTextWatcher() { @Override public void onTextChanged(String text) { Amount =(text!=null&&text!="")?Double.valueOf(text):0.0; } }; } @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) { exception.printStackTrace(); } } //XML CODE <com.mycompany.myproj.Widgets.MyEditText android:id="@+id/expense_cost" android:layout_width="match_parent" android:layout_height="match_parent" android:inputType="numberDecimal" android:maxLength="6" android:selectAllOnFocus="true" app:addTextChangedListener="@{expense.amountWatcher}" app:userVal="@{expense.Amount}" /> 

Greetings

0
source

All Articles