Чи справді працює тег Android XML "включити" тег?


84

Я не можу замінити атрибути під час використання <include> у файлах макета Android. Коли я шукав помилки, я виявив відхилене випуск 2863 :

"тег include порушено (перевизначення параметрів макета ніколи не працює)"

Оскільки Ромен вказує, що це працює в тестових наборах та на його прикладах, я, мабуть, роблю щось не так.

Мій проект організований так:

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>

А портретні та альбомні квитанції .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>

Чого мені не вистачає?


На це питання посилаються інструменти розробника Android, коли ви намагаєтесь використовувати include способом, який не підтримується.
ThomasW

Відповіді:


132

Я щойно знайшов проблему. По-перше, ви можете замінити лише атрибути 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_width, і layout_height під час використання тегу <include>, якщо ви хочете замінити будь-який з атрибутів layout_ *.

Мій приклад повинен змінитись на:

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

33
Це смішно. Я ніколи не міг змусити це працювати, і я навіть бачив, що в документації згадується необхідність як висоти, так і ширини, якщо намагаються перевизначити розміри, які, як я припускав, були висотою і шириною. Однак все, що я намагався перевизначити, - це запас, який насправді не є виміром. Чому, блін, мені потрібно вказати обидва ці, або навіть будь-який із них, коли все, що я хочу змінити, це layout_marginRight? Grrr, Android, іноді ти занадто мене засмучуєш.
Артем Руссаковський

1
FYI Android Lint видасть вам помилку (параметр Layout layout_height ігнорується, крім випадків, коли layout_width також вказаний у тегу <include>), якщо ви не перевизначаєте атрибути height і width
двійковий файл

10

Я подав запит на вдосконалення, щоб дозволити замінити всі включені атрибути:

Припустимо, у мене є два однакові макети, крім значень TextViewполя. В даний час я або змінив макет під час виконання, або продублював XML.

Наприклад, для передачі двох параметрів зі значеннями "hello" і "world" layout1:

<include layout="@layout/layout1a" params="textView=hello|editText=world" />

layout1a.xml:

<merge><TextView text="@param/textView"><EditText hint="@param/editText"></merge>

Альтернативна реалізація порушить інкапсуляцію та дозволить оператору include замінити такі значення, як:

<include layout="@layout/layout1b" overrides="@id/textView.text=hello|@id/editText.hint=world" />

layout1b.xml:

<merge><TextView id="@+id/textView"><EditText hint="@+id/editText"></merge>


1
Беручи до уваги нові матеріали для прив'язки даних, <include>зараз їх використовують ще частіше, заміщення attr - це справді обов'язкова особливість
Дмитро Грязін

1

Я виявив, що іноді пропускаю включення тегу android: id під час використання графічного графічного інтерфейсу в Eclipse. Переконавшись (коли я помічаю), я додаю в TextView від конструктора, ідентифікатор, який я використовую в макеті ListView.

<TextView android:text="@+id/textView1"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />
...

стає

<TextView android:id="@+id/textView1"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />
...

Замість того, щоб отримувати 'false', 'false' я отримую :) і включає роботу нормально.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.