I'm trying to create a custom Android control that contains a LinearLayout. You can think of it as an extended LinearLayout with fancy borders, a background, an image on the left...
I could do it all in XML (works great) but since I have dozens of occurences in my app it's getting hard to maintain. I thought it would be nicer to have something like this:
/* Main.xml */
<MyFancyLayout>
<TextView /> /* what goes inside my control's linear layout */
</MyfancyLayout>
How would you approach this? I'd like to avoid re-writing the whole linear layout onMeasure / onLayout methods. This is what I have for the moment:
/* MyFancyLayout.xml */
<TableLayout>
<ImageView />
<LinearLayout id="container" /> /* where I want the real content to go */
</TableLayout>
and
/* MyFancyLayout.java */
public class MyFancyLayout extends LinearLayout
{
public MyFancyLayout(Context context) {
super(context);
View.inflate(context, R.layout.my_fancy_layout, this);
}
}
How would you go about inserting the user-specified content (the TextView in main.xml) in the right place (id=container)?
Cheers!
Romain
----- edit -------
Still no luck on this, so I changed my design to use a simpler layout and decided to live with a bit of repeated XML. Still very interested in anyone knows how to do this though!
You can create your MyFancyLayout class by extending LinearLayout. Add the three constructors which call a method ("initialize" in this case) to set up the rest of the Views:
Within initialize, you do anything you need to to add the extra views. You can get the LayoutInflater and inflate another layout:
Or you can create Views in code and add them:
If you're going to use the Context a lot, you can store a reference to it in your constructors and use that rather than
getContext()
to save a little overhead.just use something like this:
Useful link - http://www.anddev.org/creating_custom_views_-_the_togglebutton-t310.html
This approach saves me a lot of code! :)
As esteewhy explains, just swap the xml-defined contents into where you want them internally in your own layout, in
onFinishInflate()
. Example:I take the contents that I specify in the xml:
... and move them to my internal
LinearLayout
calledcontents
where I want them to be:Combined with custom XML attributes things gets very maintainable.
This exact question bugged me for some time already but it's only now that I've solved it.
From a first glance, the problem lies in the fact that a declarative content (TextView in Your case) is instantiated sometime after ctor (where we're usually inflating our layouts), so it's too early have both declarative and template content at hand to push the former inside the latter.
I've found one such place where we can manipulate the both: it's a onFinishInflate() method. Here's how it goes in my case:
A labeled_layout.xml referenced above is not unlike something like this:
Now (still omitting some details) elsewhere we might use it like this: