androidandroid-layoutandroid-databindingaddtextchangedlistenerandroid-include

How to add onTextChanged listener to an include layout xml by databinding in android


I have an issue to add onTextChanged to a TextInputEditText in an include layout.

There is a base_edittext_view.xml as below:

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


<android.support.design.widget.TextInputLayout
    android:id="@+id/textInputLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColorHint="@color/colorPrimaryText"
    android:background="@drawable/textinputlayout_background"
    app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout">

    <android.support.design.widget.TextInputEditText
        android:id="@+id/edittextItem"
        style="@style/TextStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/input_border_bottom"
        android:cursorVisible="true"
        android:drawableEnd="@drawable/ic_user"
        android:drawablePadding="@dimen/padding_medium"
        android:gravity="center|left"
        android:hint="@string/email"
        android:inputType="textEmailAddress"
        android:maxLength="50"
        android:paddingBottom="@dimen/padding_medium"
        android:paddingTop="@dimen/padding_medium"
        android:paddingEnd="@dimen/padding_xlarge"
        android:paddingStart="@dimen/padding_medium"
        android:textColor="@color/edittext_text_color"
        android:textColorHint="@color/edittext_hint_text_color"
        android:textSize="@dimen/textsize_medium"
      />

   <!---->

</android.support.design.widget.TextInputLayout>

I want to add a onTextChanged listener to a layout which include base_edittext_view.xml.

android:onTextChanged="@{(text, start, before, count) -> viewModel.onTextChanged(text)}"

There is no problem for adding onClick to include layout but for onTextChanegd I don't know how I can achieve it.

Note:

     <include
                android:id="@+id/edittextEmail"
                layout="@layout/edittext_email_base_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/padding_xxxxlarge"
                />

Solution

  • You can do it by passing onTextChanged to included layout. See example -

    This is base_edittext_view.xml

    <data>
    
        <variable
            name="onTextChanged"
            type="androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged" />
    </data>
    
    <com.google.android.material.textfield.TextInputEditText
       ...            
       android:onTextChanged="@{onTextChanged}" />
    

    Now you can pass onTextChanged to included layout like below.

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <include
            layout="@layout/base_edittext_view"
            app:onTextChanged="@{(text, start, before, count) -> viewModel.onTextChanged(text)}"/>
    
    </LinearLayout>
    

    -------------That's it!

    There can be MANY other ways to implement it. I would like to share you COMPLETE INFORMATION.

    WAY 2

    You can make another data variable in parent layout. And include it to included layout like above. Like below-

    <data>
    
        <variable
            name="onTextChanged"
            type="androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged" />
    </data>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <include
            layout="@layout/base_edittext_view"
            app:onTextChanged="@{onTextChanged}" />
    
    </LinearLayout>
    

    And then you can implement OnTextChanged in Activity/ViewModel (wherever you need).

    binding.setOnTextChanged(new TextViewBindingAdapter.OnTextChanged() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // do you work.
        }
    });
    

    WAY 3

    OR if you don't want take another variable in parent layout, then you can directly pass onTextChanged to included layout from Java/Kotlin class. See example-

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <include
            android:id="@+id/includedEditText"
            layout="@layout/base_edittext_view"
            />
    
    </LinearLayout>
    

    Then from Java class-

    binding.includedEditText.setOnTextChanged(new TextViewBindingAdapter.OnTextChanged() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
         // your work
        }
    });
    

    There can be many other ways too. Like making custom method in ViewModel/Activity and call that method from layout.