Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a CustomView class and I want to use xml layout for it. So, my class extends RelativeLayout , inflates xml layout and tries to attach it to self.

public class CustomView extends RelativeLayout
  public CustomView (Context context)
     super(context);
     LayoutInflater.from(context).inflate(R.layout.layers_list_item, this, true);

If my xml layout has some layout (Linear, for example) as root element it works fine. But when I try to use <merge> tag according to this response I got this error:

<merge /> can be used only with a valid ViewGroup root and attachToRoot=true

My xml layout is like:

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

I also tried to remove all attributes from <merge... > tag, got the same result. What's wrong?

UPDATE: The code above is correct. As secretlm mentioned, problem was that <merge> was used as a root element and inflated in another piece od code:

ArrayAdapter<String> adapter = 
    new ArrayAdapter<String>(this, 
                             R.layout.layers_list_item, 
                             R.id.layers_list_item_text);

And with every element added adapter tried to inflate R.layout.layers_list_item which have <merge> as root.

you can't use <merge> as a root element in your final layout without container element. "Using this as the root element is useful when you know that this layout will be placed into a layout that already contains the appropriate parent View to contain the children of the element. This is particularly useful when you plan to include this layout in another layout file using and this layout doesn't require a different ViewGroup container" -- from "developer.android.com"

This example show that how to work with <merge>: http://www.coderzheaven.com/2011/06/26/merge-two-layout-xml-in-android/

Updated:

You should try with Constructor(Context, AttributeSet) from this example. I think it will solve your problem.

file test.xml:

<?xml version="1.0" encoding="utf-8"?>
<merge
 xmlns:android="http://schemas.android.com/apk/res/android">
     <CheckBox
        android:id="@+id/layers_list_item_switch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@id/layers_list_item_root"    
        android:layout_alignParentRight="true"
        android:layout_marginLeft="15dp"        
        android:button="@drawable/ic_launcher" />
     <TextView
        android:id="@+id/layers_list_item_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="left|center_vertical"
        android:layout_toLeftOf="@id/layers_list_item_switch"
        android:selectAllOnFocus="true"
        android:text="tret"
        android:ellipsize="marquee"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:marqueeRepeatLimit="marquee_forever"
        android:singleLine="true"
        android:scrollHorizontally="true"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        android:textStyle="bold"
        android:typeface="serif"
        android:clickable="true" />
</merge>

Test class which extend from RelativeLayout:

public class Test extends RelativeLayout
    public Test(Context context, AttributeSet attrs) {
        super(context, attrs);      
        LayoutInflater.from(context).inflate(R.layout.test, this, true);    

Main activity:

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

Main layout:

<com.example.testlayout.Test
    xmlns:android="http://schemas.android.com/apk/res/android"           
    android:id="@+id/layers_list_item_root"
    android:layout_height = "fill_parent"
    android:layout_width = "fill_parent"      
                <merge> isn't root element - it is attached to CustomView, which is RelativeLayout.  Anyway, there is also another layout at higher level - that CustomView just describes ListView item.
– Frederic Blase
                Dec 26, 2012 at 12:15
                well, you were right about root element - xml with <merge> as a root was used in ArrayAdapter constructor, and inflated inside it caused the error
– Frederic Blase
                Dec 27, 2012 at 13:16
                why  Test class implementation is required ? Just replacing <merge> tag by <RelativeLayout> with valid layout_width and layout_height will also work in this case
– Napolean
                Jan 4, 2018 at 8:28
Make sure to specify the complete path from source root in the main layout like this
`<com.example.testlayout.Test      xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layers_list_item_root"
    android:layout_height = "fill_parent"
    android:layout_width = "fill_parent"      
and not like this 
`<Test      xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layers_list_item_root"
    android:layout_height = "fill_parent"
    android:layout_width = "fill_parent"      
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.