Як вказати ідентифікатор, коли використання включає в макет xml файл


117

У свій макет xml-файл я включив інший макет xml-файл (кожен з іншим андроїд-ідентифікатором).

<include layout="@layout/view_contact_name" android:id="+id/test1"/>
<include layout="@layout/view_contact_name" android:id="+id/test2"/>

Але коли я запускаю його в емуляторі та запускаю програму перегляду ієрархії, у кожному макеті все ще відображається "NO_ID", і в моєму коді я findViewById(R.id.test1)і findViewById(R.id.test2)обидва повертає нуль.

Чи хтось, будь ласка, допоможе мені з моєю проблемою?


6
У ваших ідентифікаторах відсутній @символ.
AutonomousApps

Відповіді:


288

Вкажіть ідентифікатор у <include>

<include layout="@layout/test" android:id="@+id/test1" />

Потім використовуйте два findViewByIdдля доступу до полів у макеті

View test1View = findViewById(R.id.test1);
TextView test1TextView = (TextView) test1View.findViewById(R.id.text);

Використовуючи такий підхід, ви можете отримати доступ до будь-якого поля в будь-якому, що є у вас є.


18
Цей метод повертає мені нульове значення для об’єкта test1View.
Нірав Шах

4
Я не бачу різниці, ви можете пояснити?
Goddchen

30
Я дізнався, що якщо макет, який ми включили, використовує об'єднання, це не допоможе. Але у випадку, коли злиття не використовується, це працює.
Златко

@ Zlatko Yep, і це не може працювати mergeнавіть теоретично, тому що результат включення a merge- це не один погляд, а купа їх. Так що це нормально.
Відображувати ім’я

1
Це буде працювати лише в тому випадку, якщо злиття не використовується. У разі злиття неможливо, як зазначено тут: code.google.com/p/android/isissue/detail?id=36918#c3
Захід Рашид

61

Я з’ясував, що якщо ви використовуєте <merge>тег у своєму макеті include, то ідентифікатор включає перенесення до тегу злиття, який не є реальним поданням.

Тому або видаліть злиття, або замініть його на якийсь макет.

Тор Норбі написав :

<include>Тег нереальний вигляд, тому findByView годі й шукати. Атрибут @id (та будь-які інші атрибути, встановлені на тезі include), замість цього застосовується до кореневого тегу включеного макета. Тож ваша Activity.getView (R.id.included1) насправді повинна бути <TextView>самою собою.


3
Хороший. Я видаляю тег злиття, і він починає працювати, але моє запитання тут полягає в тому, яке використання тегу злиття, якщо який-небудь включає макет, що працює без нього?
Ankur Chaudhary

35

Ромен Гай вказує, що ви можете замінити ідентифікатор включеного макета, помістивши android:idатрибут всередині <include>тегу.

<include android:id="@+id/cell1" layout="@layout/workspace_screen" />

1
Це вірно. Спосіб посилання на кореневий елемент у включеному файлі макета - за допомогою ідентифікатора, вказаного в тезі «включати» (якщо він не вказаний).
Том R

1
Ідентифікатор у <include> = ідентифікатор root у включеному макеті
Fadils

Мені здається, якщо я спершу встановлю ідентифікатор (у тезі include він переосмислює ідентифікатор із включеного макета, правда?), У мене буде тег "включення", який буде спочатку "@ + id / cell1", а потім макет = ' @ layout / workspace_screen 'замінить android: id знову з ідентифікатором включеного макета. @Ron Romero відповіді для мене більше сенсу.
Неонова війна

14

Я думаю, що у верхній відповіді пропущено найважливіший момент і може ввести людей в оману думати, що <include/>тег створює представлення, яке містить вміст включення.

Ключовий момент є те, що включає в себе'S ідентифікатор буде прийнятий в кореневих зору включається'S файл макет.

Це означає, що це:

// activity_main.xml
<include layout="@layout/somelayout" android:id="@+id/someid"/>

// somelayout.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

Стає таким:

// activity_main.xml
<ImageView
    android:id="@+id/someid"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

4

так, це так, але обережно, коли макет, вставлений у поле include, є спеціальним, і ви хочете отримати доступ до цього коріннього макета. Цей макет у цьому випадку @ layout / test test фактично повертається в першому рядку.

test test1View = (test)findViewById(R.id.test1);

2
  1. Ви повинні встановити ідентифікатор кожного тегу включення
  2. включений дочірній елемент встановлює новий ідентифікатор. якщо ви шукаєте, як створити новий ідентифікатор, подивіться цей запис: https://stackoverflow.com/a/15442898/1136117

2

Проблема полягає в тому, що ми намагаємось використовувати ідентифікатор, який не задекларований у поточному файлі макета. Замість того, щоб декларувати ще раз, id можна просто посилати за допомогою @+id/. Якщо ви рефакторне оригінальне ідентифікаційне ім'я через Android Studio, він також робить рефактор у включеному макеті.

<include layout="@layout/toolbar"/>

<TextView
    android:id="@+id/txt_description"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    **android:layout_below="@+id/toolbar"**
    android:layout_marginTop="16dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"/>

2

У разі використання <RecyclerView>знаходження ідентифікатора <include>за допомогою екземпляра завищеного перегляду, інакше він повернеться в нулевий .

public class ViewHolder extends RecyclerView.ViewHolder {

        private mTextView;

        public ViewHolder(View view) {
            super(view);
            View include_1 = view.findViewById(R.id.include_1);
            mTextView = (TextView) include_1.findViewById(R.id.text_id);
        }
    }

1

Якщо ви встановили ідентифікатор для будь-якого кореневого тегу включеного макета, ви можете використовувати цей ідентифікатор або ви можете встановити ідентифікатор для включеного макета.

Але ви не можете встановити ідентифікатор обом, це може кинути виняток.

<include layout="@layout/view_contact_name" android:id="+id/test1"/>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

....
</LinearLayout>

Або

<include layout="@layout/view_contact_name"/>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        android:id="@+id/llBottomMainView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

....
</LinearLayout>

0

Якщо говорити про включення, у вас є або ідентифікатор у кореневому представленні всередині включеного файлу макета, або у самій рядку включення, а не в обох. Наприклад:

<include layout="@layout/layout1" android:id="@+id/layout1"/>

Макет 1 файл

<RelativeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/layout2">

</RelativeLayout>

Наведений вище приклад помилковий, оскільки технічно у вас є два ідентифікатори, оголошені для одного макета. Отже, ви повинні вибрати, який елемент матиме ідентифікатор.


0

Нічого собі, я не можу повірити, що на це питання ще немає правильної відповіді. Це прості теги смоктати. Ви можете змінити лише те, що починається з того, android:layout_що android:idне відповідає. Тож відповідь - ти не можеш. Вибачте. Замість цього можна створити клас, який буде ViewGroup, який буде надувати включені представлення всередині, а потім додавати це як тег у ваш макет, але це про це.

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