Setting attribute of child element of included layout
Asked Answered
B

4

47

I have a main.xml file describing the layout of my main activity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <include layout="@layout/mylayout" />
    <include layout="@layout/mylayout" />
    <include layout="@layout/mylayout" />
    <include layout="@layout/mylayout" />
    <include layout="@layout/mylayout" />
    <include layout="@layout/mylayout" />

</LinearLayout>

and its included layout xml file (mylayout.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mylayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello world" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

I just want to include "mylayout" in my main layout 5 times, but instead of seeing "hello world" 5 times, I want the TextView to contain custom text.

Is there any way to do this by setting some attribute on the include element to override the child TextView's text? What would be the best approach to take to accomplish this?

Benumb answered 26/1, 2012 at 2:28 Comment(1)
This seems like a serious limitation that should be fixed. I just submitted a bug report.Lapoint
C
19

No, there is no way to pass parameters to the included layout other than the layout params using the <include> directive.

You can inflate the layout programatically and add them to your view. Add an id to the container in your main layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" />

Then in your Activity:

ViewGroup container = (ViewGroup)findViewById(R.id.container);
for (int i = 0; i < 6; i++) {
    View myLayout = getLayoutInflater.inflate(R.layout.mylayout, null);
    TextView tv = myLayout.findViewById(R.id.textView);
    tv.setText("my layout " + i);
    container.addView(myLayout); // you can pass extra layout params here too
}
Corrosive answered 26/1, 2012 at 2:44 Comment(1)
don't forget to add the dataBinding element to your build.gradle file in the app module android { ... dataBinding { enabled = true } }Tactical
P
12

It is possible if you enable data binding:

In reuse_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
       <variable name="text" type="String"/>
    </data>
    <LinearLayout 
        android:id="@+id/mylayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{text}" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>
</layout>

when you call the reuse_layout.xml just add app:text attribute with it

<layout="@layout/reuse_layout" app:text="some tex" />
Petard answered 22/6, 2017 at 6:31 Comment(6)
Where does app:text get defined, as I am getting this error: "Error:(461) Error parsing XML: unbound prefix" when I compile and it is complaining about app:text attribute. Thanks!Salford
In the layout "reuse_layout.xml" is where you can define variables. when you try to prase the data use prefix app: then followed by the name of the variable. I guess you try to send the string by using @string right? in this case please use app:text="@{@string/your_string_key}"Petard
Thanks, I guess there is just something I'm missing, because I get that error even with the code above copied as-is.Salford
I am getting this error: "Error:(461) Error parsing XML: unbound prefix"Schnauzer
You need xmlns:app="http://schemas.android.com/apk/res-auto" in the root element (layout) to use the app: prefix. Then you'll need to place the literal string in a data-binding expression for it to be picked up, e.g., app:text="@{&quot;some text&quot;}". See https://mcmap.net/q/341339/-android-data-binding-attribute-not-found .Germanic
don't forget to add the dataBinding element to your build.gradle file in the app module android { ... dataBinding { enabled = true } }Tactical
N
5

https://developer.android.com/training/improving-layouts/reusing-layouts.html

You can set the android:id property of each include. That gives the id to the root element of the layout being included.

Get that view by id then find the subview you want to change the text on.

Nardone answered 26/1, 2012 at 2:38 Comment(3)
Also I'm answering on my phone so its hard to type.Nardone
I'm trying to see if there is a way to do this in the layout XML rather than in code. Is that not possible?Benumb
I also met such problem and find that reusing the complex layout several times cost too much code to fill the property. Maybe it is better to copy paste same structure in layout xml.Capon
S
1

I think I found an easy way, but it could create a lot of boilerplate code if the use case is high. but it's working perfectly for me

First Step:

Add data binding element to your build.gradle file in the app module

android{
...
dataBinding { enabled = true }
...
}

Second Step:

Create a layout file for your reusable 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">

    <data>
        <variable
            name="text"
            type="String" />
    </data>

    <com.google.android.material.card.MaterialCardView
        android:id="@+id/card"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="@color/sortBtnBG"
        app:contentPadding="5dp"
        app:strokeColor="@color/cardStrokeColor"
        app:strokeWidth="1dp">

        <TextView
            android:id="@+id/card_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@{text}"
            android:textColor="@color/black"
            android:textSize="16sp" />
    </com.google.android.material.card.MaterialCardView>



</layout>

add id for the elements you need to change, in my case, I am changing the text

Third Step:

Use your layout in your activity layout using <include/>

 <LinearLayout
        android:id="@+id/sorting_options"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp">

         <include layout="@layout/your_layout_name"
          android:id="@+id/customCard1"/>
     

          <include layout="@layout/your_layout_name"
          android:id="@+id/customCard2"/>

</LinearLayout>

make sure your give id to the <inlcude/>

Final Step:

In your activity.java file add this:

View custom_card1 = findViewById(R.id.customCard1);
TextView cc1 = view.findViewById(R.id.card_text);
cc1.setText("hello");

View custom_card2 = findViewById(R.id.customCard2);
TextView cc2 = view.findViewById(R.id.card_text);
cc2.setText("word");
Sestos answered 25/10, 2021 at 5:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.