Як я можу призначити ідентифікатор для перегляду програмно?


202

У XML-файлі ми можемо призначити ідентифікатор такому виду, як android:id="@+id/something"і потім викликати findViewById(), але при створенні перегляду програмно, як я призначу ідентифікатор?

Я думаю, setId()це не те саме, що призначення за замовчуванням. setId()є додатковою.

Хтось може мене виправити?


1
Підгрупа: як генерувати унікальні ідентифікатори: stackoverflow.com/questions/1714297 / ...
Чіро Сантіллі郝海东冠状病六四事件法轮功

Відповіді:


521

idОгляд Android

Android id- це ціле число, яке зазвичай використовується для ідентифікації представлень; це idможе бути призначено за допомогою XML (коли це можливо) та за допомогою коду (програмно.) idНайбільш корисно для отримання посилань для визначених XML Views, породжених Inflater(наприклад, за допомогою setContentView.)

Призначити idчерезXML

  • Додайте атрибут android:id="@+id/SomeName "до вашої думки.
  • Коли ваша програма буде побудована, android:idприсвоюється унікальний int для використання код.
  • Посилальна свій android:id«сек intзначення в коді з допомогою" R.id.SomeName "(фактично константи) .
  • це intможе змінитися від збирання до складання, тому ніколи не копіюйте ідентифікатор з gen/пакета.name/ R.java, просто використовуйте " R.id.somename".
  • (Крім того, idпризначений для PreferenceXML не використовується, коли його Preferenceгенерується View.)

Призначення idза допомогою коду (програмно)

  • Вручну встановити ids за допомогою someView.setId(int);
  • Обов'язково intмає бути позитивним, але в іншому випадку довільним - це може бути все, що завгодно (читайте, якщо це страшно.)
  • Наприклад, якщо створити та нумерувати кілька переглядів, що представляють елементи, ви можете використовувати їх номер.

Унікальність idс

  • XML-призначені ids будуть унікальними.
  • Присвоєні кодом ids не повинні бути унікальними
  • idТеоретично присвоєний коду може конфліктувати з XML-знаками id.
  • Ці конфліктні ids не мають значення, якщо їх правильно запитувати (тримати читання) .

Коли (і чому) конфліктні ids не мають значення

  • findViewById(int)буде повторювати глибину спочатку рекурсивно через ієрархію подання з вказаного Вами представлення і поверне перше, Viewщо знайде, зі збігом id.
  • Поки до ієрархії, idвизначеної XML, не визначено коду id, findViewById(R.id.somename)завжди повертатиме визначений XML View так id'd.

Динамічне створення переглядів та призначення IDs

  • У макеті XML визначте порожнє ViewGroupс id.
  • Такі як LinearLayoutс android:id="@+id/placeholder".
  • Використовуйте код для заповнення заповнювач ViewGroupз Viewс.
  • Якщо вам потрібно чи хочете, призначте будь- idякі, зручні для кожного перегляду.
  • Запросити ці дочірні представлення за допомогою placeholder.findViewById (удобнийInt);

  • Представлено API 17, View.generateViewId()який дозволяє генерувати унікальний ідентифікатор.

Якщо ви вирішите зберігати посилання на свої погляди навколо , не забудьте створити їх getApplicationContext()та встановіть для кожного посилання нульове значення onDestroy. Мабуть витоку на Activity(висить на це після того, як знищується) марнотратно .. :)

Зарезервуйте XML android:idдля використання в коді

Представлено API 17, View.generateViewId() який генерує унікальний ідентифікатор. (Завдяки шансам-внести зміни до вказівки на це.) *

Якщо ваш ViewGroupнеможливо визначити за допомогою XML (або ви не хочете, щоб це було), ви можете зарезервувати ідентифікатор за допомогою XML, щоб переконатися, що він залишається унікальним:

Тут значення / ids.xml визначає спеціальний id:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="reservedNamedId" type="id"/>
</resources>

Після того, як створено ViewGroup або View, ви можете приєднати спеціальний ідентифікатор

myViewGroup.setId(R.id.reservedNamedId);

Конфліктний idприклад

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

макет / mylayout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:id="@+id/placeholder"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
</LinearLayout>

Щоб імітувати конфлікт, давайте скажемо, що наша остання збірка присвоїла R.id.placeholder( @+id/placeholder) intзначення 12 ..

Далі, MyActivity.java визначає деякі додавання переглядів програмно (за допомогою коду):

int placeholderId = R.id.placeholder; // placeholderId==12
// returns *placeholder* which has id==12:
ViewGroup placeholder = (ViewGroup)this.findViewById(placeholderId);
for (int i=0; i<20; i++){
    TextView tv = new TextView(this.getApplicationContext());
    // One new TextView will also be assigned an id==12:
    tv.setId(i);
    placeholder.addView(tv);
}

Отже, placeholderі один з наших нових TextViews має id12! Але це насправді не є проблемою, якщо ми запитуємо представлення дітей, що містять заповнювачі:

// Will return a generated TextView:
 placeholder.findViewById(12);

// Whereas this will return the ViewGroup *placeholder*;
// as long as its R.id remains 12: 
Activity.this.findViewById(12);

*Не так вже і погано


9
На додаток до цього, комусь, хто кодує подібні рішення, може бути корисно знати про View.generateViewId () в API> 17 для безконфліктних ідентифікаторів
AllDayAmazing

Зауважте, що findViewByIdпроводиться перше глибинне дослідження, так що "поки в ієрархії немає ідентифікованих кодом ідентифікаторів, призначених над визначеним XML ідентифікатором", технічно не правильно; це "раніше", а не "нагорі".
Кару

В останніх версіях інструментів для розробників Android програмне встановлення ідентифікатора на довільне значення буде позначено як помилка компілятора. Очікується, що значення буде фактичним ідентифікатором ресурсу.
ThomasW

Я вважаю, що це було навіть тоді, коли я відповів на це п’ять років тому - саме тому потрібно було визначити користувацькі ідентифікатори ids.xml. Для справді довільних ідентифікаторів використовуйте View.generateViewId()(API 17). (Будь ласка, уточніть свою точку, якщо я її пропустив.)
CodeShane

> (Також ідентифікатор, присвоєний налаштуванням у XML, не використовується, коли налаштування генерує його перегляд.) Дуже зацікавлений у цьому. Мій код успадковується від PreferenceDialogFragmentCompatцього, схоже, ідентифікатори R.idне відповідають ієрархії перегляду. Таким чином я не можу знайти вид за ідентифікатором.
УРК

6

Ви можете просто використовувати View.setId(integer)для цього. У XML, навіть якщо ви встановлюєте ідентифікатор String, він перетворюється на ціле число. Завдяки цьому ви можете використовувати будь-яке (позитивне) ціле число для Views додавання програмно.

Відповідно до Viewдокументації

Ідентифікатор не повинен бути унікальним у ієрархії цього перегляду. Ідентифікатор повинен бути додатним числом.

Таким чином, ви можете використовувати будь-яке додатне ціле число, яке вам подобається, але в цьому випадку можуть бути деякі перегляди з еквівалентними ідентифікаторами. Якщо ви хочете шукати деякий вигляд в ієрархії, який вимагає встановити тег з деякими ключовими об'єктами, може бути корисним.

Подяка за цю відповідь .


5

Так, ви можете зателефонувати setId(value)в будь-якому огляді з будь-яким (позитивним) цілим значенням, яке вам подобається, а потім знайти його в батьківському контейнері, використовуючи findViewById(value). Зауважте, що setId()для різних переглядів братів та сестер дійсно дзвонити з однаковим значенням, але findViewById()повертатиметься лише перший.


1
Зауважте, що вам потрібно використовувати ціле число, що перевищує нуль.
Пітер Айтай

хоча findViewById (int) буде повторювати рекурсивно через ієрархію подання з вказаного представлення перегляду та повертає перший перегляд, який він знайде, з відповідним ідентифікатором, визначеним у 1-й відповіді, є найбільш точним.
Анікет Такур

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