Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Android XML Layout's 'include' Tag Really Work?

I am unable to override attributes when using <include> in my Android layout files. When I searched for bugs, I found Declined Issue 2863:

"include tag is broken (overriding layout params never works)"

Since Romain indicates this works in the test suites and his examples, I must be doing something wrong.

My project is organized like this:

res/layout   buttons.xml  res/layout-land   receipt.xml  res/layout-port   receipt.xml 

The buttons.xml contains something like this:

<LinearLayout      xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:orientation="horizontal">    <Button .../>    <Button .../> </LinearLayout> 

And the portrait and landscape receipt.xml files look something like:

<LinearLayout     xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:orientation="vertical">    ...    <!-- Overridden attributes never work. Nor do attributes like        the red background, which is specified here. -->   <include       android:id="@+id/buttons_override"       android:background="#ff0000"       android:layout_width="fill_parent"       layout="@layout/buttons"/>  </LinearLayout> 

What am I missing?

like image 806
Eric Burke Avatar asked Apr 13 '10 17:04

Eric Burke


People also ask

What does the tag in an XML layout file do?

The <include> tag lets you to divide your layout into multiple files: it helps dealing with complex or overlong user interface.

What an XML layout file contains?

Specifically, Android considers XML-based layouts to be resources, and as such, layout files are stored in the reslayout directory inside your Android project. Each XML file contains a tree of elements specifying a layout of widgets and containers that make up one View.

What is XML tag Android?

XML tags define the data and used to store and organize data. It's easily scalable and simple to develop. In Android, the XML is used to implement UI-related data, and it's a lightweight markup language that doesn't make layout heavy. XML only contains tags, while implementing they need to be just invoked.


2 Answers

I just found the issue. First, you can only override layout_* attributes, so the background won't work. That is documented behavior and simply an oversight on my part.

The real problem is found in LayoutInflater.java:

// We try to load the layout params set in the <include /> tag. If // they don't exist, we will rely on the layout params set in the // included XML file. // During a layoutparams generation, a runtime exception is thrown // if either layout_width or layout_height is missing. We catch // this exception and set localParams accordingly: true means we // successfully loaded layout params from the <include /> tag, // false means we need to rely on the included layout params. ViewGroup.LayoutParams params = null; try {    params = group.generateLayoutParams(attrs); } catch (RuntimeException e) {    params = group.generateLayoutParams(childAttrs); } finally {    if (params != null) {      view.setLayoutParams(params);    } } 

If the <include> tag does not include both layout_width and layout_height, the RuntimeException occurs and is silently handled, without any log statement even.

The solution is to always include both layout_width and layout_height when using the <include> tag, if you want to override any of the layout_* attributes.

My example should change to:

<include       android:id="@+id/buttons_override"       android:layout_width="fill_parent"       android:layout_height="wrap_content"       layout="@layout/buttons"/> 
like image 57
Eric Burke Avatar answered Oct 11 '22 11:10

Eric Burke


I submitted an enhancement request to allow all included attributes to be overridden:

Suppose I have two identical layouts other than the values of a TextView field. Presently, I either have modify the layout at runtime or duplicate the XML.

For example to pass two parameters with values "hello" and "world" to layout1:

<include layout="@layout/layout1a" params="textView=hello|editText=world" />

layout1a.xml:

<merge><TextView text="@param/textView"><EditText hint="@param/editText"></merge>

An alternate implementation would break encapsulation and would allow the include statement to override values like:

<include layout="@layout/layout1b" overrides="@id/textView.text=hello|@id/editText.hint=world" />

layout1b.xml:

<merge><TextView id="@+id/textView"><EditText hint="@+id/editText"></merge>

like image 29
Jeff Axelrod Avatar answered Oct 11 '22 11:10

Jeff Axelrod