我试图做到这一点 - 我想要一个视图,在左侧有一个按钮,在右侧有一个按钮,但是中间可以有任意内容(取决于谁在包含它)。基本上是一个自定义视图组,可以在XML布局中具有子视图,并将这些子视图与另一个XML布局包装。以下是我的做法:
top_bar.xml:表示用来包装内容的常见布局。请注意LinearLayout(可以是任何布局)带有ID“addChildrenHere” -稍后会引用它。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/topBarLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left" />
<LinearLayout
android:id="@+id/addChildrenHere"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right" />
</LinearLayout>
main.xml: 主要布局。其中包括一个自定义的viewgroup(WrappedLayout)和几个子项。请注意它声明了一个自定义的XML命名空间,并在WrappedLayout标签上设置了两个自定义属性(这些属性指定应该用哪个布局来包装子项,以及此节点中的子项应该放置在那个布局中的哪个位置)。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:karl="http://schemas.android.com/apk/res/karl.test"
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<karl.test.WrappedLayout
android:id="@+id/topBarLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
karl:layoutToInflate="@layout/top_bar"
karl:childContainerID="@+id/addChildrenHere">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is a child of the special wrapper."
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is another child; you can put anything here."
android:textAppearance="?android:attr/textAppearanceMedium" />
</karl.test.WrappedLayout>
</LinearLayout>
attrs.xml:这个文件放在res/values目录下。它定义了上面XML中使用的自定义XML属性。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="WrappedLayout">
<attr name="layoutToInflate" format="integer"/>
<attr name="childContainerID" format="integer"/>
</declare-styleable>
</resources>
最后,WrappedLayout.java:这个文件处理读取自定义属性,并进行一些技巧性的操作,使addView()实际上将视图添加到不同的位置。
package karl.test;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public class WrappedLayout extends FrameLayout
{
private ViewGroup mChildContainer;
public WrappedLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
final int layoutToInflate;
final int childContainerID;
{
final TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.WrappedLayout);
layoutToInflate = styledAttributes.getResourceId(R.styleable.WrappedLayout_layoutToInflate, 0);
childContainerID = styledAttributes.getResourceId(R.styleable.WrappedLayout_childContainerID, 0);
styledAttributes.recycle();
}
if(layoutToInflate == 0
|| childContainerID == 0)
{
Log.e("Error", "WrappedLayout.WrappedLayout(): Error reading custom attributes from XML. layoutToInflate = " + layoutToInflate + ", childContainerID =" + childContainerID);
}
else
{
final View inflatedLayout = View.inflate(context, layoutToInflate, this);
mChildContainer = (ViewGroup)inflatedLayout.findViewById(childContainerID);
}
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params)
{
if(mChildContainer == null)
{
super.addView(child, index, params);
}
else
{
mChildContainer.addView(child, index, params);
}
}
}
据我所知,这个可以工作。但是在Eclipse布局编辑器中效果不太好(我不确定问题出在哪里),但您可以正常查看布局。更改WrappedLayout的子项似乎需要手动编辑XML。