How to extend include tag on Android
I ended up having many xml files sharing the same code on the header and footer. Is there any good way to create some kind of template and to pass it a resource to include in the middle ?
In other words, how to extend the Include tag in such a way I could, rather than simply include a view, include a template which includes the given resource ?
My messy code:
<?xml version="1.0" encoding="utf-8"?>
<include layout="@layout/settings_section" />
settings_section.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--Header Begin-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@layout/my_shape"
android:orientation="vertical"
><include layout="@layout/header" />
<!--End header-->
<TextView
开发者_开发知识库 android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:text="Blah blah blah"
/>
<!--Footer Begin -->
</LinearLayout>
</LinearLayout>
<!-- Footer End -->
What I would like:
<include layout="@layout/header" />
<com.example.Include layout="@layout/settings_section" inside="@layout/default_template" />
EDIT: I'm looking for code samples.
This doesn't answer your question exactly but I've used styles for similar situations.
res/layout/layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/header1" >
<LinearLayout
style="@style/header2" >
<include layout="@layout/header" />
...
res/values/styles.xml
...
<style name="header1">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:orientation">vertical</item>
<item name="android:padding">10dp</item>
</style>
<style name="header2">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:background">@layout/my_shape</item>
<item name="android:orientation">vertical</item>
<style>
...
Anyway, this approach simplifies parts you have to copy/paste into multiple files and makes modifying them rather straightforward and flexible. You can make modifications within layout.xml if needed - values you give in styles are overwritten - and modifying style affects all layouts using them.
Just an idea: inside of settings_section
xml I would create a container (a LinearLayout
) with id. Then in Activity.onCreate()
I would find that container by its id and add a child (default_template
) to it.
Then I would create some kind of YourBaseActivity
with a protected method addContent(int contentId)
, so the code to find a container and insert a content to it is not repeated across other similar activities.
If you want the behaviour you describe then it is possible - you will have to make a custom view class that extends LinearLayout
(see Building Custom Components). When this view is created it can get the attributes specified in the XML (see Passing custom variables via XML resources), and inflate these resources.
The settings XML would look like
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@layout/my_shape"
android:orientation="vertical"
><include layout="@layout/header" />
<!--End header-->
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:text="Blah blah blah"
/>
<!--Footer Begin -->
</LinearLayout>
Note that I've gotten rid of the outermost LinearLayout
for the content since your custom view will be a type of LinearLayout
anyway. If I have time I'll knock up a DoubleInclude
view later and post the code.
here is a xml template
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/myviewHeader"
android:layout_height="wrap_content"
android:layout_width="fill_parent" >
</TextView>
<LinearLayout
android:id="@+id/myviewIncluder"
android:layout_height="wrap_content"
android:layout_width="fill_parent" >
</LinearLayout>
<TextView
android:id="@+id/myviewFooter"
android:layout_height="wrap_content"
android:layout_width="fill_parent" >
</TextView>
</LinearLayout>
and a Class for a ViewGroup with dynamic Content
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MyView extends ViewGroup {
private LayoutInflater mInflater;
private TextView header;
private TextView footer;
public MyView(Context context,View child) {
super(context);
mInflater = LayoutInflater.from(context);
mInflater.inflate(R.layout.myview, this);
LinearLayout includer = (LinearLayout) findViewById(R.id.myviewIncluder);
header = (TextView) findViewById(R.id.myviewHeader);
footer = (TextView) findViewById(R.id.myviewFooter);
includer.addView(child);
}
@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
// TODO Auto-generated method stub
}
public void set_HeaderText(String text){
header.setText(text);
}
public void set_FooterText(String text){
footer.setText(text);
}
}
If you want to add a vie in the Includer part, yozu may act like this:
View include = null;
LayoutInflater mInflater = LayoutInflater.from(this);
include = mInflater.inflate(R.xml.list_item_icon_text,null);
ViewGroup text = new MyView(this,include);
The default Eclipse build system isn't very flexible from what I've seen, but if your willing to go with Ant for your build system, you can do a lot more at build time like generating XML files. Eclipse can use Ant to build the project instead of it's own build system as that's common for some projects. By generating the XML files at build time instead of runtime as @Arhimed suggested, you have the benefit of seeing the file XML source and of rendering it in Eclipse to make sure it looks correct. This approach is a bit more advanced, but it offers much more flexibility. Once you are using Ant, you can also do other things like generate two versions of an app with different settings, such as a paid version and a lite version. Here's Ant's intro to FilterChains: http://ant.apache.org/manual/Types/filterchain.html and a document on using Ant for customs builds of an Android apk: http://blog.elsdoerfer.name/2010/04/29/android-build-multiple-versions-of-a-project/
精彩评论