简体   繁体   English

如何解决:“在使用自定义视图实现双向数据绑定时,找不到属性'android:text'”的getter?

[英]How to solve: “cannot find getter for attribute 'android:text'” when implementing two-way data binding with custom view?

I went through many kinda-similar questions but none of the answers seemed to solve my problem. 我经历了许多类似的问题,但没有一个答案似乎解决了我的问题。 I implemented a custom EditText that I want to be compatible with two-way data binding. 我实现了一个自定义EditText ,我希望与双向数据绑定兼容。 The problem is, every time I try to compile I get the error: 问题是,每次我尝试编译时都会收到错误:

Error:java.lang.IllegalStateException: failed to analyze: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Cannot find the getter for attribute 'android:text' with value type java.lang.String on com.app.toolkit.presentation.view.CustomEditText. file:/Users/humble-student/Home/workspace/android/application/app/src/main/res/layout/login_view.xml loc:68:8 - 81:69 ****\ data binding error ****

    at org.jetbrains.kotlin.analyzer.AnalysisResult.throwIfError(AnalysisResult.kt:57)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules(KotlinToJVMBytecodeCompiler.kt:137)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:158)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:61)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:107)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:51)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:92)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$2.invoke(CompileServiceImpl.kt:386)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$2.invoke(CompileServiceImpl.kt:96)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:892)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:96)
    at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:919)
    at 

Here is my implementation: 这是我的实现:

CustomEditText CustomEditText

class CustomEditText @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    // ...
    private lateinit var editText_input: EditText
    private lateinit var textView_errorMessage: TextView

    private var isErrorDisplayed = false
    private var inputTextOriginalColor: ColorStateList? = null

    init {
        orientation = VERTICAL
        clearContainerFormatting()

        createEditTextInput(context, attrs, defStyleAttr)
        createTextViewErrorMessage(context)

        addView(editText_input)
        addView(textView_errorMessage)
    }

    fun setError(message: String) {
        //...
    }

    fun getText(): String = editText_input.text.toString()

    fun setText(text: String) = editText_input.setText(text)

    // ...
}

Model 模型

data class SampleData(
        private var _content: String
) : BaseObservable() {
    var content: String
        @Bindable get() = _content
        set(value) {
            _content = value
            notifyPropertyChanged(BR.content)
        }
}

Client that uses the CustomView with data binding 使用带有数据绑定的CustomView的客户端

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="android.view.View" />

        <variable
            name="data"
            type="SampleData" />

        <variable
            name="presenter"
            type="SamplePresenter" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"
        tools:context=".sample_view.presentation.view.SampleView">

        <NotificationPopup
            android:id="@+id/notificationPopup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clipToPadding="false"
            android:elevation="4dp"
            app:allowManualExit="true" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView_mirror"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:fontFamily="sans-serif"
                android:text="@{data.content}"
                android:textSize="16sp"
                android:textStyle="bold"
                tools:text="test" />

            <CustomEditText
                android:id="@+id/customEditText_sample"
                style="@style/RegisterInput"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Type anything"
                android:text="@={data.content}" />

            <Button
                android:id="@+id/button_validateInput"
                style="@style/Widget.AppCompat.Button.Colored"
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:layout_marginEnd="8dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="8dp"
                android:onClick='@{(v) -> presenter.onValidateDataClick(customEditTextSample.getText())}'
                android:text="Validate Input" />
        </LinearLayout>
    </RelativeLayout>
</layout>

PS: If I replace CustomEditText for regular EditText widget, it works perfectly PS:如果我将CustomEditText替换为常规的EditText小部件,它可以很好地工作

Funny but I was able to find a great post on medium that helped me with this issue. 有趣,但我能够在媒体上找到一个很好的帖子 ,帮助我解决这个问题。 Basically what I needed was a CustomEditTextBinder : 基本上我需要的是CustomEditTextBinder

@InverseBindingMethods(
        InverseBindingMethod(
                type = CustomEditText::class,
                attribute = "android:text",
                method = "getText"
        )
)
class CustomEditTextBinder {
    companion object {
        @JvmStatic
        @BindingAdapter(value = ["android:textAttrChanged"])
        fun setListener(editText: CustomEditText, listener: InverseBindingListener?) {
            if (listener != null) {
                editText.addTextChangedListener(object : TextWatcher {
                    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {

                    }

                    override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {

                    }

                    override fun afterTextChanged(editable: Editable) {
                        listener.onChange()
                    }
                })
            }
        }

        @JvmStatic
        @BindingAdapter("android:text")
        fun setText(editText: CustomEditText, text: String?) {
            text?.let {
                 if (it != editText.text) {
                     editText.text = it
                 }
            }
         }

It might seem weird but you don't actually need to call it anywhere, just add the class and the framework will take care of finding it through the annotation processing. 它可能看起来很奇怪但你实际上并不需要在任何地方调用它,只需添加类,框架将负责通过注释处理找到它。 Note that the setText is really really important in order to prevent infinite loops. 请注意, setText确实非常重要,以防止无限循环。 I also added: 我还补充说:

var text: String?
    get() = editText_input.text.toString()
    set(value) {
        editText_input.setText(value)
    }

fun addTextChangedListener(listener: TextWatcher) =
        editText_input.addTextChangedListener(listener)

on CustomEditText . CustomEditText

Here is an example of the implementation 这是一个实现例子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 双向数据绑定 Android。 找不到接受参数类型“”的 &lt;&gt; 的 getter - Two-way data binding Android. Cannot find a getter for <> that accepts parameter type '' Android 自定义视图上的双向数据绑定。 找不到吸气剂 - Android two way data binding on custom View. Cannot find getter Android:具有双向绑定的复合或自定义视图 - Android: Compound or Custom view with two-way binding android:enabled属性的双向数据绑定 - Two-way data binding for android:enabled attribute 双向绑定 - 数据绑定 Android - Two-Way Binding - Data Binding Android msg:在数据绑定中找不到值为java.lang.String的属性&#39;android:text&#39;的getter? - msg:Cannot find the getter for attribute 'android:text' with value type java.lang.String in data binding? 在Android中使用双向数据绑定时如何修复找不到符号view-model-name-BindingImpl - How to fix cannot find symbol view-model-name-BindingImpl when using two-way databinding in Android Android数据绑定-找不到属性的获取器 - Android Data-binding - Cannot find the getter for attribute 双向绑定Android上的编辑文本 - Two-way binding Android on edit text NavigationDrawer中的Android双向数据绑定 - Android Two-Way Data Binding in NavigationDrawer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM