EditText

时间:2016-09-12 07:41:56

标签: android android-databinding

在Android中,我们可以在变量前面使用与@=的双向数据绑定。但是,该变量是double。因此,要在EditText中显示,我需要使用String将其转换为String.valueOf(pojo.value)

如果我在前面附加=以进行双向数据绑定,那么它就不会编译。

如果我附加onTextChanged并在那里设置值,我会丢失光标。有没有解决方法?

修改

它适用于InverseBindingAdapter,但不允许输入.(句号)。

4 个答案:

答案 0 :(得分:1)

没有简单的解决方法。但是,我继续前进并创造了一种几乎像双向绑定一样的变化。

我的EditText看起来像这样:

        <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是活动的实例。它包含valueAmountChanged(EditText editText)方法。

现在,在检查了您的价值金额时,我正在解析该文本字符串并将其存储在相应的变量中。

对我来说,它看起来像这样:

 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
    } 

现在,当我们更改userAmount变量时,它会反映出我们已在app:userVal中使用EditText参数设置绑定适配器。

因此,使用绑定适配器检查新值是否不是当前值,然后更新该值。否则,保持原样。我们需要这样做,因为如果用户正在键入并且绑定适配器更新该值,那么它将松散是光标位置并将其带到前面。所以,这将拯救我们。

@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
        }
    }

这是一种典型的方法,我知道。但是,找不到比这更好的了。还有非常少的文档可用,其他文档以博客文章的形式出现,应该已添加到官方文档中。

希望它有所帮助。

答案 1 :(得分:1)

这就是我的做法。

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

    @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}"/>

EditText具有以下设置以强制正确输入

    android:inputType="numberDecimal"

答案 2 :(得分:0)

您的解决方案部分适用于我。 我使用了@BindingAdaptor和&#39; Amount&#39;变量值反映在编辑文本中,但OnTextChangeListner没有在值更改时触发。所以我在VM中使用了TextWatcher。 VM和XML的代码都在这里。没有什么可写在活动中。

//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}" />

干杯

答案 3 :(得分:0)

这对我有用:

<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" />