Как программно назначить идентификатор для представления? - PullRequest
192 голосов
/ 11 декабря 2011

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

Я думаю, setId() - это не то же самое, что назначение по умолчанию. setId() это дополнительно.

Кто-нибудь может меня поправить?

Ответы [ 3 ]

508 голосов
/ 06 ноября 2012

Android id обзор

Android id - это целое число, обычно используемое для идентификации представлений; id может быть назначено с помощью XML (когда это возможно) и с помощью кода (программно.). id наиболее полезно для получения ссылок на определенные XML-значения View, сгенерированные Inflater (например, с помощью setContentView.)

Назначить id через XML

  • Добавьте атрибут android:id="@+id/ somename " к вашему представлению.
  • Когда ваше приложение создано, android:id будет присвоено уникальное int для использования в коде.
  • Ссылка на ваше значение android:id int в коде с использованием "R.id. somename" (фактически, константа.)
  • это int может меняться от сборки к сборке , поэтому никогда не копировать идентификатор из gen/ package.name / R.java, просто используйте "R.id. somename" .
  • (Кроме того, id, присвоенный Preference в XML, не используется, когда Preference генерирует его View.)

Назначить id через код (программно)

  • Ручная настройка id с использованием someView.setId( int );
  • int должно быть положительным, но в противном случае оно может быть произвольным - оно может быть любым, что вы хотите (продолжайте читать, если это ужасно.)
  • Например, если вы создаете и нумеруете несколько видов, представляющих элементы, вы можете использовать их номер элемента.

Уникальность id с

  • XML - назначенный id s будет уникальным.
  • Назначенный код id с не должен быть уникальным
  • Назначенный код id s может (теоретически) конфликтовать с XML -направленным id s.
  • Эти конфликтующие id s не будут иметь значения, если их правильно запросить (продолжайте читать) .

Когда (и почему) конфликтующие id s не имеют значения

  • findViewById(int) будет рекурсивно выполнять итерацию в глубину по иерархии представлений из указанного вами представления и возвращать первое найденное View с совпадающим id.
  • Пока нет назначенных кодов id, назначенных до XML-определенного id в иерархии, findViewById(R.id.somename) всегда будет возвращать определенное XML-представление, поэтому id 'd.

Динамическое создание видов и назначение ID s

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

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

Если вы решите сохранить ссылки на свои представления вокруг , обязательно создайте для них экземпляр с помощью getApplicationContext() и обязательно установите каждую ссылку на ноль в onDestroy. Очевидно, утечка Activity (зависание на нем после уничтожения) расточительна ..:)

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

API 17 представил View.generateViewId() , который генерирует уникальный идентификатор. (Благодаря take-chances-make-Changes для указания на это.) *

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

Здесь values ​​/ 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 и один из наших новых TextView имеют id 12! Но на самом деле это не проблема, если мы запрашиваем дочерние представления заполнителя:

// 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);

* Не так уж и плохо

6 голосов
/ 11 декабря 2011

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

Согласно View документации

Идентификатор не имеетбыть уникальным в иерархии этого представления.Идентификатор должен быть положительным числом.

Таким образом, вы можете использовать любое положительное целое число, которое вам нравится, но в этом случае могут быть некоторые представления с эквивалентными идентификаторами.Если вы хотите найти какое-то представление в иерархии, может пригодиться вызов setTag с некоторыми ключевыми объектами.

Кредиты для этот ответ .

5 голосов
/ 11 декабря 2011

Да, вы можете вызвать setId(value) в любом представлении с любым (положительным) целочисленным значением, которое вам нравится, и затем найти его в родительском контейнере, используя findViewById(value). Обратите внимание, что допустимо вызывать setId() с одним и тем же значением для разных родственных представлений, но findViewById() вернет только первое.

...