Android - Writing a custom (compound) component

Tom van Zummeren picture Tom van Zummeren · Sep 25, 2009 · Viewed 29.5k times · Source

The Android app I'm currently developing has a main activity that has grown quite large. This is mainly because it contains a TabWidget with 3 tabs. Each tab has quite a few components. The activity has to control of all those components at once. So I think you can imagine that this Activity has like 20 fields (a field for almost every component). Also it contains a lot of logic (click listeners, logic to fill lists, etc).

What I normally do in component based frameworks is to split everything up into custom components. Each custom component would then have a clear responsibility. It would contain it's own set of components and all other logic related to that component.

I tried to figure out how this can be done, and I found something in the Android documentation what they like to call a "Compound Control". (See http://developer.android.com/guide/topics/ui/custom-components.html#compound and scroll to the "Compound Controls" section) I would like to create such a component based on an XML file defining the view structure.

In the documentation it says:

Note that just like with an Activity, you can use either the declarative (XML-based) approach to creating the contained components, or you can nest them programmatically from your code.

Well, that's good news! The XML-based approach is exactly what I want! But it doesn't say how to do it, except that it is "like with an Activity"... But what I do in an Activity is call setContentView(...) to inflate the views from XML. That method is not available if you for example subclass LinearLayout.

So I tried to inflate the XML manually like this:

public class MyCompoundComponent extends LinearLayout {

    public MyCompoundComponent(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.my_layout, this);
    }
}

This works, except for the fact that the XML I'm loading has LinearLayout declared as the root element. This results in the inflated LinearLayout being a child of MyCompoundComponent which itself already is a LinearLayout!! So now we have a redundant LinearLayout in between MyCompoundComponent and the views it actually needs.

Can somebody please provide me with a better way to approach this, avoiding having a redundant LinearLayout instantiated?

Answer

bhatt4982 picture bhatt4982 · Sep 25, 2009

Use merge tag as your XML root

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Your Layout -->
</merge>

Check this article.