我今天遇到了这个问题。不管它值多少钱,我认为有一个直截了当的工作。不要向包含标签添加属性,而是为包含创建一个自定义包装器视图并为其添加属性。然后,从包装器中包含。让包装类实现提取属性并传递给它的单个孩子,这是包含布局的根视图。
因此,假设我们为一个名为 SingleSettingWrapper 的包装器声明了一些自定义属性,如下所示 -
<declare-styleable name="SingleSettingWrapper">
<attr name="labelText" format="string"/>
</declare-styleable>
然后,我们创建两个自定义视图类 - 一个用于包装器 (SingleSettingWrapper),另一个用于将包含的子视图 (SingleSettingChild) -
<!-- You will never end up including this wrapper - it will be pasted where ever you wanted to include. But since the bulk of the XML is in the child, that's ok -->
<com.something.SingleSettingWrapper
android:id="@+id/wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:labelText="@string/my_label_string">
<!-- Include the child layout -->
<include layout="@layout/setting_single_item"/>
</com.something.SingleSettingWrapper>
对于孩子,我们可以在其中放置我们想要的任何复杂布局。我只会放一些基本的东西,但实际上你可以包括任何东西 -
<com.something.SingleSettingItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout >
<!-- add whatever custom stuff here -->
<!-- in this example there would be a text view for the label and maybe a bunch of other stuff -->
<!-- blah blah blah -->
</RelativeLayout>
</com.something.SingleSettingItem>
对于包装器(这是关键),我们在构造函数中读取了所有自定义属性。然后,我们覆盖 onViewAdded() 并将这些自定义属性传递给我们的孩子。
public class SingleSettingWrapper extends FrameLayout
{
private String mLabel;
public SingleSettingWrapper(Context context, AttributeSet attrs)
{
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SingleSettingWrapper,
0, 0);
mLabel = a.getString(R.styleable.SingleSettingWrapper_labelText);
a.recycle();
}
public void onViewAdded(View child)
{
super.onViewAdded(child);
if (!(child instanceof SingleSettingItem))
return;
((TextView)child.findViewById(R.id.setting_single_label)).setText(mLabel);
/*
Or, alternatively, call a custom method on the child implementation -
((SingleSettingItem)child)setLabel(mLabel);
*/
}
}
或者,您也可以实现孩子,让它从包装器接收消息并修改自身(而不是让包装器像我上面那样修改孩子)。
public class SingleSettingItem extends LinearLayout
{
public SingleSettingItem(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public void setLabel(String l)
{
// set the string into the resource here if desired, for example
}
}
在一天结束时,您想要<include>
布局的每个 XML 文件都将包含大约 7 行 XML 用于包装器+包含而不是您想要的单个包含,但是如果包含的视图包含数百行您再好不过了。例如 -
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- this is the beginning of your custom attribute include -->
<com.something.SingleSettingWrapper
android:id="@+id/my_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:labelText="@string/auto_lock_heading">
<include layout="@layout/setting_single_item"/>
</com.something.SingleSettingWrapper>
<!-- this is the end of your custom attribute include -->
</LinearLayout>
在实践中,这似乎工作得很好,而且设置起来也相对简单。我希望它可以帮助某人。