今日、この問題に遭遇しました。それが何であれ、私は簡単な回避策があると思います。include タグに属性を追加する代わりに、include のカスタム ラッパー ビューを作成し、それに属性を追加します。次に、ラッパーからインクルードを実行します。ラッパー クラスの実装で属性を抽出し、インクルード レイアウトのルート ビューである単一の子に渡します。
たとえば、SingleSettingWrapper というラッパーのカスタム属性を次のように宣言するとします。
<declare-styleable name="SingleSettingWrapper">
<attr name="labelText" format="string"/>
</declare-styleable>
次に、2 つのカスタム ビュー クラスを作成します。
<!-- 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
}
}
結局のところ、レイアウトしたい XML ファイルのそれぞれには、<include>
必要な単一のインクルードではなく、ラッパー + インクルードの約 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>
実際には、これはかなりうまく機能しているようで、設定も比較的簡単です。誰かの役に立てば幸いです。