1. ホーム
  2. android

[解決済み] Android XML Layoutのincludeタグは本当に有効か?

2023-06-16 18:21:20

質問

Android のレイアウトファイルで <include> を使用すると、属性を上書きすることができません。バグを検索したところ、Declined 課題2863 :

includeタグが壊れています(レイアウトパラメータのオーバーライドが機能しません)。

Romain はこれがテスト・スイートと彼の例で動作することを示しているので、私は何か間違ったことをしているに違いありません。

私のプロジェクトはこのように構成されています。

res/layout
  buttons.xml

res/layout-land
  receipt.xml

res/layout-port
  receipt.xml

buttons.xmlには、このような内容が書かれています。

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

  <Button .../>

  <Button .../>
</LinearLayout>

そして、縦長と横長のreceipt.xmlファイルは、以下のような感じです。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

  ...

  <!-- Overridden attributes never work. Nor do attributes like
       the red background, which is specified here. -->
  <include
      android:id="@+id/buttons_override"
      android:background="#ff0000"
      android:layout_width="fill_parent"
      layout="@layout/buttons"/>

</LinearLayout>

何が足りないのでしょうか?

どのように解決するのですか?

今、問題を発見しました。まず、layout_* 属性しかオーバーライドできないので、背景は機能しません。これは文書化された動作であり、単に私の見落としです。

本当の問題はLayoutInflater.javaで見つかります。

// We try to load the layout params set in the <include /> tag. If
// they don't exist, we will rely on the layout params set in the
// included XML file.
// During a layoutparams generation, a runtime exception is thrown
// if either layout_width or layout_height is missing. We catch
// this exception and set localParams accordingly: true means we
// successfully loaded layout params from the <include /> tag,
// false means we need to rely on the included layout params.
ViewGroup.LayoutParams params = null;
try {
   params = group.generateLayoutParams(attrs);
} catch (RuntimeException e) {
   params = group.generateLayoutParams(childAttrs);
} finally {
   if (params != null) {
     view.setLayoutParams(params);
   }
}

もし、<include>タグに layout_width と layout_height の両方を含まない場合、RuntimeException が発生し、ログに記録されることもなく、黙って処理されます。

解決策は、layout_* 属性のいずれかを上書きしたい場合、<include> タグを使用するときに、常に layout_width と layout_height の両方を含めることです。

私の例は、次のように変更する必要があります。

<include
      android:id="@+id/buttons_override"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      layout="@layout/buttons"/>