除了一个部分外,我有几个大致相同的布局文件。有没有办法让我可以在一个地方拥有共同的XML;而不是复制/粘贴,并且当我想要进行1次更改时必须更新一堆文件?
我知道我可以从其他XML文件中包含XML,但是公共代码不是内部控件;它是外包装;所以包括不起作用。基本上,我有一堆文件看起来像这样:
<LinearLayout
android:id="@+id/row"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ImageView android:layout_height="26dp"
android:id="@+id/checkImage"
android:layout_width="26dp"
android:layout_alignParentTop="true"
android:scaleType="fitCenter"/>
<!-- Different types of views go here depending on which layout file it is -->
<ImageButton android:layout_height="fill_parent"
android:id="@+id/playButton"
android:layout_width="42dp"
android:src="@drawable/play_button"
android:scaleType="center"
android:background="#00000000"/>
</LinearLayout>
基本上,我想做ASP.Net对Master Pages的处理。这有什么选择吗?
答案 0 :(得分:6)
解决方案很简单。
您需要将onCreate()
函数SetContentView中的“活动”类扩展到基本xml布局,还需要覆盖基本活动类中的setContentView
例如:
1.使用以下代码
创建base_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/image_view_01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="50dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/base_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</LinearLayout>
</LinearLayout>
BaseActivity.java
public class BaseActivity extends Activity {
ImageView image;
LinearLayout baseLayout;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.base_layout);
this.image = (ImageView) this.findViewById(R.id.image_view_01);
this.baseLayout = (LinearLayout) this.findViewById(R.id.base_layout);
this.image.setImageResource(R.drawable.header);
}
@Override
public void setContentView(int id) {
LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(id, this.baseLayout);
}
}
和SomeActivity.java
public class SomeActivity extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.some_layout);
//rest of code
}
}
到目前为止我唯一注意到的是,当请求进度条(requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS))时,需要在调用super.onCreate之前完成。我认为这是因为在调用此函数之前还没有任何东西可以绘制。
这对我很有用,希望你会发现这对你自己的编码很有用。
答案 1 :(得分:1)
也许您可以使用一个主布局XML文件,然后根据需要通过代码动态添加/删除其他小部件。
答案 2 :(得分:1)
我试图做到这一点 - 我想要一个左侧有一个按钮,右侧有一个按钮的视图,但中间可能有任意内容(取决于谁包含它)。基本上是一个自定义视图组,它可以在XML布局中具有子视图,并将使用另一个XML布局包装这些子视图。我是这样做的:
top_bar.xml:这表示包装内容的常用布局。请注意具有ID“addChildrenHere”的LinearLayout(可以是任何布局) - 稍后会引用它。
<?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:主要布局。这包括一个带有几个孩子的自定义视图组(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:它处理读取自定义属性,并做一些hackery使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
{
///Attempts to add children to this layout will actually get forwarded through to mChildContainer.
///This would be final, but it's actually used indirectly by the constructor before it's initialised.
private ViewGroup mChildContainer;
public WrappedLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
//read the custom attributes
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
{
//inflate the layout and (implicitly) add it as a child view
final View inflatedLayout = View.inflate(context, layoutToInflate, this);
//grab the reference to the container to pass children through to
mChildContainer = (ViewGroup)inflatedLayout.findViewById(childContainerID);
}
}
///All the addView() overloads eventually call this method.
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params)
{
if(mChildContainer == null)
{
//still inflating - we're adding one of the views that makes up the wrapper structure
super.addView(child, index, params);
}
else
{
//finished inflating - forward the view through to the child container
mChildContainer.addView(child, index, params);
}
}
}
据我所知,这是有效的。 Eclipse布局编辑器不能很好地工作(我不太确定问题是什么),但你可以很好地查看布局。更改WrappedLayout的子项似乎需要手动编辑XML。
答案 3 :(得分:0)