'error: <identifier> expecte when setting up binding adapters for two way data binding
I am trying to setup two way binding for TextInputEditText with Float variable.
Here is the entire content of my DataBindingAdapters class.
object DataBindingAdapters {
@BindingAdapter("android:text")
@JvmStatic
fun setText(view: TextInputEditText, value: Float) {
if(value != view.text.toString().toFloat()) {
view.setText(value.toString())
}
}
@InverseBindingAdapter(attribute = "android:text")
fun getText(view: TextInputEditText): Float {
return view.text.toString().toFloat()
}
}
But I am getting:
error: <identifier> expected
float callbackArg_0 = mBindingComponent.null.getText(inputFieldSize);
What am i missing?
Solution 1:[1]
You miss one more binding adapter, as mentioned in the InverseBindingAdapter documentation:
@BindingAdapter(value = [ "android:textAttrChanged"], requireAll = false)
fun setTextWatcher( view: TextInputEditText, textAttrChanged: InverseBindingListener?) {
val newValue = object: TextWatcher {
override fun afterTextChanged(s: Editable?) = Unit
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged( s:CharSequence, start:Int, before:Int, count:Int) {
textAttrChanged?.onChange()
}
}
val oldValue = ListenerUtil.trackListener(view, newValue, R.id.textWatcher)
if (oldValue != null) {
view.removeTextChangedListener(oldValue)
}
view.addTextChangedListener(newValue)
}
When you create @InverseBindingAdapter(attribute = "android:text"), an event android:textAttrChanged is created, and you have to add a binding adapter for it.
Calling textAttrChanged?.onChange() will trigger the InverseBindingAdapter that you created.
EDIT:
Also, you are using Kotlin so you don't need to put your binding adapters in an object. A separate file will suffice. Just remove wrapping object DataBindingAdapters {..} and @JvmStatic and you should be fine.
Solution 2:[2]
I have the same issue,
the fix is:
class MyView {
companion object {
@BindingAdapter("android:text")
@JvmStatic
fun setText(view: TextInputEditText, value: Float) {
if(value != view.text.toString().toFloat()) {
view.setText(value.toString())
}
}
@InverseBindingAdapter(attribute = "android:text")
fun getText(view: TextInputEditText): Float {
return view.text.toString().toFloat()
}
}
}
Besides this, you may/have to add textAttrChanged event also. If it needs then it will tell you xxx: textAttrChanged not found...... error. Then add below method just side the companion object body
@BindingAdapter(value = ["android:textAttrChanged"], requireAll = false)
@JvmStatic fun setValue(view: MyView, textAttrChanged: InverseBindingListener) {
val newValue = object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
textAttrChanged.onChange()
}
}
view.binding.editText.addTextChangedListener(newValue)
}
Besides this, you might get warnings in above code.
Then you can use:
object XXXAdapter {
//Put the binding methods here.
}
to silence the warnings.
Solution 3:[3]
I had the same issue and was able to solve it by making the inverse binding adapter static like in the official documentation:
@InverseBindingAdapter(attribute = "android:text")
@JvmStatic fun getText(view: TextInputEditText): Float {
return view.text.toString().toFloat()
}
Note the @JvmStatic right before fun getText(.... This is the only change from the code in your question.
BTW: Mohru's answer also mentions this in the edit-section, but at least for me it was not obvious enough to be found in the first place ;)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | Torben |
