Search code examples
androidxmldata-bindingparametersinclude

Pass data to <include> layout using Databinding


I've been searching this a lot today and only found some unclear answers regarding this question.

I'm having multiple TextView and EditText in a form, all of them being customised by my theme and i'd like to reuse the same included layout each time, but having parameters to it like the text inside the TextView or hint inside the EditText.

My form.xml right now:

<LinearLayout android: orientation="horizontal">
     <TextView android:text="Username"/>
     <EditText android:id="edittext_username"
               android:hint="Enter username..."
               android:inputType="text"/>
</LinearLayout>

<LinearLayout android: orientation="horizontal">
     <TextView android:text="Password"/>
     <EditText android:id="edittext_password"
               android:hint="Enter password..."
               android:inputType="password"/>
</LinearLayout>

... other fields ...

What i'd like in the main form.xml:

<LinearLayout android:orientation="vertical" ...>
     <include layout="form_edittext" 
            app:textview_text="@{`Username`}"
            app:edittext_hint="@{`Enter username...`}"
            ... other parameters ...
 />
     <include layout="form_edittext"
            app:textview_text="@{`Password`}"
            app:edittext_hint="@{`Enter password...`}"
            ... other parameters ...
 />
</LinearLayout>

also the form_edittext.xml:

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

    <data>
        <variable name="textview_text" type="java.lang.String"/>
        <variable name="edittext_id" type="java.lang.String"/>
        <variable name="edittext_inputType" type="java.lang.String"/>
        <variable name="edittext_hint" type="java.lang.String"/>
    </data>

    <TextView android:text="@{textview_text}"/>
    <EditText android:id="@{edittext_id}"
                   android:hint="@{edittext_hint}"
                   android:inputType="@{edittext_inputType}"/>
</layout>

I'm still a beginner and i do not know if this is possible. On this post, the guy replied he used data binding (as in example shown by me) How to Re-using Layouts with <include/> with parameters? (you may see the first answer).

However, using this method give me the error of XML not recognizing identifiers like "textview_text" (the variables that i'm accessing via @{...}. If you got other solutions i'd appreciate if you share them. Cheers!

UPDATE on iCantC's answer: (but the textview's text and the hint remain empty). Main layout:

<?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">

 ...
            <include layout="@layout/activity_login_layout_input"
                android:id="@+id/activity_login_layout_input_emailAddress"
                app:textviewt="@{@string/email}"     //the string is "Email Address"
                app:edittexth="@{@string/emailhint}" />     //the string is "Your email address..."

 ...
</layout>

Included layout:

<layout>

    <data>
        <variable
            name="textviewt"
            type="String"/>
        <variable
            name="edittexth"
            type="String"/>
    </data>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical"
        android:showDividers="middle">

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{textviewt}"
            android:textColor="@color/c1"
            android:textSize="12sp"/>

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="26dp">

            <androidx.appcompat.widget.AppCompatEditText
                android:id="@+id/edittext"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center|start"
                android:layout_marginStart="26dp"
                android:background="@drawable/activity_login_background"
                android:hint="@{edittexth}"
                android:padding="6dp"
                android:textAlignment="center"
                android:textColor="@color/c2"
                android:textColorHint="@color/grey"
                android:textSize="14sp"/>

            <androidx.appcompat.widget.AppCompatImageView
                android:layout_width="36dp"
                android:layout_height="36dp"
                android:layout_gravity="start"
                android:adjustViewBounds="true"
                android:src="@drawable/activity_login_edittext_drawable" />

        </FrameLayout>

    </LinearLayout>

</layout>

Solution

  • It seems like you want to include a common layout and then pass dynamic parameters from the main layout to included layout, here are the steps,

    Step 1: Enable DataBinding in your project

    //In the build.gradle file in the app module, add this 
    
    android {
        ...
        dataBinding {
            enabled = true
        }
    }
    
    

    Step 2: Create your common_layout_included.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layout>
    
    <data>
        <variable  
            name="username"
            type="String"/>
    </data>
    
    <LinearLayout
            ..
            >
    
    <TextView
        android:id="@+id/tv_username"
        android:text="@{username}"/> 
    
       </LinearLayout>
    
    </layout>
    

    Step 3: Include common_layout_included.xml in your main_layout.xml

    <?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">
    
        <LinearLayout
            ..
            >
    
            <include
                android:id="@+id/includedLayout"
                layout="@layout/common_layout_included"
                app:username="@{@string/username}" // here we pass any String 
                />
    
        </LinearLayout>
    </layout>
    
    

    Step 4: Make sure you inflate the layout using DataBinding way

    //In the onCreate of your Activity
    
    val binding = DataBindingUtil.setContentView(this,R.layout.main_layout)
    
    

    That's it, you are good to go. If still some error appears just do File -> Invalidate Caches/Restart

    One last thing, I saw that you are assigning the id's to the view's dynamically android:id="@{edittext_id}", in all of my experience, I never really encountered a use case where I would be motivated to do this. I don't even know if it's possible and even if possible I doubt it's a good practice.