TrongVu
TrongVu

Reputation: 33

Android - Make new view attribute and pass to its children in XML compound view component - data binding in layout

Full answer:

1. Enable data binding in app/build.gradle:

dataBinding {
   enabled true
}

2. Use DataBindingUtil to set content view

java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    DataBindingUtil.setContentView(this, R.layout.activity_engineering_mode_main);
}

3. Child item layout

You will see that I define 2 new attributes

values/bools.xml

<variable
    name="textTitle"
    type="String" />

<variable
    name="buttonVisibility"
    type="boolean" />

With textTitle, you can use any string from resource by @string/string_name

With buttonVisibility, you have to define bool resource type, and use @bool/bool_name

layout/item_engineering_list_row.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>

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

    <variable
        name="textTitle"
        type="String" />

    <variable
        name="buttonVisibility"
        type="boolean" />
</data>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="@dimen/engineer_actionbar_height"
    android:background="@color/engineer_background_color"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/engineer_txtName"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="@dimen/engineer_text_margin"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:text="@{textTitle}"
        android:textColor="@color/engineer_text_color"
        android:textSize="@dimen/engineer_title_font_size" />

    <Button
        android:id="@+id/engineer_btnNext"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginRight="@dimen/engineer_text_margin"
        android:text="BACK"
        android:visibility="@{buttonVisibility ? View.VISIBLE : View.GONE, default=gone}" />

</LinearLayout>
</layout>

4. Boolean resource file

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="item_button_visibility_default">false</bool>
    <bool name="item_button_visibility_on">true</bool>
    <bool name="item_button_visibility_off">false</bool>
</resources>

5. Parent layout, which includes some children and passes value to new attributes

<?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
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include
        android:id="@+id/includedLayout0"
        layout="@layout/item_engineering_list_row"
        app:buttonVisibility="@{@bool/item_button_visibility_on}"
        app:textTitle="@{@string/app_name}" />
    <include
        android:id="@+id/includedLayout1"
        layout="@layout/item_engineering_list_row"
        app:buttonVisibility="@{@bool/item_button_visibility_default}"
        app:textTitle="@{@string/app_name}" />
</LinearLayout>
</layout>

Original Question:

I am new to android and I've been working with QML in QT for a time.

I wonder how I can make a layout more easier by applying params in XML in compound view components.

I have a custom layout item in xml and want to pass some attributes from a parent to its children, and I also want to initialize parent's attribute with new values to customize its children too.

My concept is as below:

item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    !!!! how to declare a new attribute here !!!
    | like this:
    | textTitle="New Title"      // default value for child
    | buttonVisibility="visible" // default value for child
    ">

    <TextView
        android:id="@+id/engineer_txtTitle"
        android:text= textTitle <--- use parent's />

    <Button
        android:id="@+id/engineer_btnBack"
        android:visibility= buttonVisibility  <== use parent's />

</LinearLayout>

CLICK HERE TO SEE IMAGE: base Item

main.xml

<LinearLayout>
    <include
        android:id="@+id/item1"
        layout="@layout/item" 
        textTitle= "FIRST"
        // buttonVisibility not set here, use default as visible
        />

    <include
        android:id="@+id/item2"
        layout="@layout/item"
        textTitle= "SECOND"
        buttonVisibility = "gone" // dont show button 
        />
 </LinearLayout>

CLICK HERE TO SEE IMAGE: apply with param

Upvotes: 2

Views: 2170

Answers (2)

Khemraj Sharma
Khemraj Sharma

Reputation: 59004

You can use Data Binding of Architecture component. Here is an sample of your requirement.

Recently I answered a question related to this. Clean answer

This example shows pass value to <include.

I have a common view layout_common.xml, I want to pass String to included layout. I will create a variable of type String. Refer that String to your TextView. I created passedText for example.

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    >

    <data>
        // declare fields
        <variable
            name="passedText"
            type="String"/>
    </data>

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{passedText}"/> //set field to your view.

</layout>

Now you can pass passedText field to your <include tag.

activity_main.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
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

        <include
            android:id="@+id/includedLayout"
            layout="@layout/layout_common"
            app:passedText="@{@string/app_name}" // here we pass any String 
            />

    </LinearLayout>
</layout>

Note that both layouts (parent & included) should be binding layout, i.e. wrapped with <layout> and </layout> tags

Upvotes: 2

TrongVu
TrongVu

Reputation: 33

Thanks @Khemraj to show the keyword "Data Binding" in Android :)

I have found the answer for me. It includes Khemraj's answer and some small code added to values resource. I posted it in my question for others to find it easily.

Upvotes: 0

Related Questions