【问题标题】:Two-way data-binding with double value in EditText在 EditText 中具有双值的双向数据绑定
【发布时间】:2016-09-12 07:41:55
【问题描述】:

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

如果我在前面附加= 进行双向数据绑定,它根本无法编译。

如果我附加一个onTextChanged 并在那里设置值,我会失去光标。有什么解决办法吗?

编辑:

它与InverseBindingAdapter 一起工作,但不允许输入.(句点)。

【问题讨论】:

  • 请检查this,给出的参考是int数据类型,你的问题是关于double,但它会帮助你
  • 谢谢!这肯定会有所帮助!
  • 它有效但不允许句号.
  • “不允许句号.”是什么意思?
  • 嗨@kirtan403 你能找到解决方案吗?我面临着类似的问题。

标签: android android-databinding


【解决方案1】:

这对我有用(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" />

【讨论】:

    【解决方案2】:

    我是这样做的。

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

    【讨论】:

      【解决方案3】:

      对此没有简单的解决方案。但是,我继续创建了一种几乎像双向绑定一样工作的更改。

      我的 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 变量时,它将反映我们在 EditText 中使用 app:userVal 参数设置绑定适配器。

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

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

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

      希望对某人有所帮助。

      【讨论】:

        【解决方案4】:

        您的解决方案部分对我有用。 我使用了@BindingAdaptor,并且“数量”变量值反映在编辑文本中,但 OnTextChangeListner 没有在值更改时触发。所以我在VM中使用了TextWatcher。 VM 和 XML 的代码都在这里。 Activity 中无需编写任何内容。

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

        干杯

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-23
          • 1970-01-01
          • 2019-12-24
          • 2011-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多