Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Data Binding - Observe edit text's value that is wrapped in custom view

I have a custom view that wraps an edit text.

I want the the observe the changes of this edit text at the class that uses this Custom View, using Data Binding.

How can I expose the input string of the edit text to the other classes that use the custom view?

Is two way data binding the only way?

In other XML:

<MyCustomView
        android:id="@+id/password_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:password="@={controller.password}"
        app:isPasswordValid="@={controller.isValid}"/>

The layout of the custom view (Linear Layout):

<merge>

    <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/security_code_input_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/email_text_view">

        <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/security_code_edit_text"
                android:background="@drawable/edittext_background"
                android:inputType="textPassword"
                android:text="@={view.pass}"
                app:onSubmit="@{() -> view.onKeyboardActionDoneClicked()}" />

    </com.google.android.material.textfield.TextInputLayout>

    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/textfield_error_invalid_password_length"
            app:visibleOrGone="@{view.showInvalidPasswordText}" />

</merge>
like image 744
RoR noob Avatar asked Dec 21 '19 20:12

RoR noob


2 Answers

If you want to use the xml syntax in your example (app:password="@=controller.password"), then you need to define static methods for 2-way data binding with @BindingAdapter and @InverseBindingAdapter annotations. You can find an official sample here (though I prefer using top-level kotlin extension functions rather than nesting them in an object since it doesn't require the @JvmStatic annotation and feels more idiomatic). You can also check out the library source for how 2-way binding adapters are defined for TextView here, though it's probably more involved than what you'd need to do for your case.

If all you need to do is observe text changes and you don't need to set the text directly on your custom view, then 2-way data binding is unnecessary and you can set some sort of listener that will call back when the text changes (which could be set via data binding if you have a public setter) or expose a LiveData<String> that you can observe (not using xml/data binding).

like image 170
Mateo Avatar answered Oct 14 '22 09:10

Mateo


I can think of 2 ways of doing this

  • Using Binding Adapter: You can pass your viewModel instance to your binding adapter. In your binding adapter you would observe editText changes and call any of the viewModel's public methods, something like this:
    @BindingAdapter("bind:doSomething")
    fun bindDoSomething(
        view: EditText,
        vm: ViewModel?
    ) {
        vm?.let {
            view.addTextChangedListener(object : TextWatcher {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                }

                override fun afterTextChanged(s: Editable?) {
                }

                override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                    vm.callFun()
                }
            })
        }
    }

and in your xml:

app:doSomething="@{vm}"
  • Using Traditional Interface Approach: Having an interface between your custom view class and your activity/fragment. The interface method can be called from onTextChanged of TextChangedListener implemented in your custom view class.

Let me know if this helps or if you have any questions

like image 43
Kunal Chaubal Avatar answered Oct 14 '22 09:10

Kunal Chaubal