CROSP
CROSP

Reputation: 4617

How does <merge> tag work internally

I am trying to understand how does <merge> tag internally work. I have studied some examples using View Hierarchy tool. So I understand basic using and how does it work on higher level, but I wanna to study more about this tag and inflating views in general.
So let's consider some simple layouts
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg"
    android:gravity="center_horizontal">

<include layout="@layout/titlebar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />

<TextView android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/some_text"
    android:text="@string/hello"
    android:padding="10dp" />

</RelativeLayout>

And of course titlebar.xml

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

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/chrome" />
</merge>

In this case we have following result.
First

Let's change our titlebar.xml

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/some_text"
    android:src="@drawable/chrome" />

The result is really forthcoming. enter image description here

Let's do more changes in our activity_main.xml file.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg"
    android:gravity="center_horizontal">

<include layout="@layout/titlebar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />

<TextView android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/bug"
    android:text="@string/hello"
    android:padding="10dp" />


    </LinearLayout>

And in titlebar.xml I left everything the same.

So in this case we have some weird things
1. Now our root layout is LinearLayout. We have specified nonexistent attribute android:layout_below="@+id/some_text" in titlebar file

  1. In the same line we have another issue @+id/some_text doesn't exist anymore, now we have @+id/bug. Let's look at the result

enter image description here

Here I have some questions :

  1. We are can use any attribute (for any layout) in merged file,but if the viewgroup(layout) where this part is included (in our case activity_main.xml) doesn't have such attributes, what how this situation is solved, just ignored as we can see in result ?

  2. We have hardcoded id of view above imageview,it works if id is exists, but if it doesn't , as we can see in result it is also just being ignored

So I have already written a lot. To sum up, where works of XML parser exactly with merged and include tags is described, also it will be good to know where sources of XML parser is located, to look through it.

I will be grateful for everyone who read this line and can suggest something or give advice.

Thx in advance.

Upvotes: 0

Views: 120

Answers (1)

FunkTheMonk
FunkTheMonk

Reputation: 10938

If an <include> tag includes both layout_width and layout_height, it will override all of the root view's (of the file it is including) layout parameters.

A merge is a way to avoid an additional depth in the view hierarchy - an XML layout file must only have 1 root - so it must either have a single View, a ViewGroup which can include additional Views or a <merge>. When you're including a layout with multiple Views inside a ViewGroup, you may be adding extra unneeded complexity to your hierarchy - for example, 2 vertically orientated LinearLayouts may not be required. The merge allows you to remove the extra ViewGroup, and merge its Views into the ViewGroup where it is included.

Including a layout with a merge with a single View is the same as just including a layout with the single View directly, except that with the merge there isn't a 'root view' of the layout, so the include will not override its layout parameters (I believe).

When a View or ViewGroup is inflated into a ViewGroup which doesn't support the layout parameters that the child specifies, the parameters are just dropped. This occurs when including or inflating (using a layout inflater).

If a child View or ViewGroup is added to a ViewGroup (using addView), it is possible that the child already has layout parameters assigned, and if they aren't compatible with the ViewGroup it is being added to, it may result in a class cast exception later on during measuring / layout.

Your second question is to do with RelativeLayouts layout rules, and its behaviour can be defined using android:layout_alignWithParentIfMissing

Upvotes: 1

Related Questions