Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two-way data-binding with double value in EditText

In Android we can use 2-way data-binding with @= in front of variable. But, that variable is a double. So for displaying it in EditText, I need to convert it to String using String.valueOf(pojo.value).

If I attach = in front for two-way data binding it simply just not compile.

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

Edit:

It worked with InverseBindingAdapter but doesn't allow . (period) to be typed.

like image 438
kirtan403 Avatar asked Sep 12 '16 07:09

kirtan403


2 Answers

Here's how I did it.

    //-------------------------------------------------------------------------------------------------//

    @BindingAdapter("app:text")
    fun setDoubleInTextView(tv: TextView, dbl: Double?) {

        try {
              //This will occur when view is first created or when the leading zero is omitted
        if (dbl == null && (tv.text.toString() == "" || tv.text.toString() == ".")) return

            //Check to see what's already there
            val tvDbl = tv.text.toString().toDouble()
            //If it's the same as what we've just entered then return
            // This is when then the double was typed rather than binded
            if (tvDbl == dbl)
                return

            //If it's a new number then set it in the tv
            tv.text = dbl?.toString()

        } catch (nfe: java.lang.NumberFormatException) {

            //This is usually caused when tv.text is blank and we've entered the first digit
            tv.text = dbl?.toString() ?: ""

        }//catch

    }//setDoubleInTextView

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//

    @InverseBindingAdapter(attribute = "app:text")
    fun getDoubleFromTextView(editText: TextView): Double? {

        return try {
            editText.text.toString().toDouble()
        } catch (e: NumberFormatException) {
            null
        }//catch

    }//getDoubleFromTextView

    //-------------------------------------------------------------------------------------------------//

    @BindingAdapter("textAttrChanged")
    fun setTextChangeListener(editText: TextView, listener: InverseBindingListener) {
        editText.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(p0: Editable?) = listener.onChange()

            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                Log.d(TAG, "beforeTextChanged $p0")
            }

            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                Log.d(TAG, "onTextChanged $p0")
            }

        })
    }

    //-------------------------------------------------------------------------------------------------//


  <EditText
    style="@style/TextAppearance.MaterialComponents.Body1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="@string/price"
    android:inputType="numberDecimal"
    app:text="@={viewModel.tempProductPrice}"/>

The EditText has the following setting to force the correct input

    android:inputType="numberDecimal"
like image 149
ShanieMoonlight Avatar answered Oct 03 '22 00:10

ShanieMoonlight


This works for me (2020):

<EditText
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="2"
    android:text="@={`` + viewModel.currentStudent.age}"    //key point!! Not single/double quote
    android:inputType="number" />
like image 40
Sam Chen Avatar answered Oct 02 '22 22:10

Sam Chen