Как я могу назначить идентификатор для просмотра программно?

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

Я думаю, что setId() не совпадает с назначением по умолчанию. setId() является дополнительным.

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

Ответ 1

Обзор 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 может измениться из сборки, чтобы построить так никогда не копировать id из gen/ package.name/R.java, просто используйте "R.id. somename".
  • (Кроме того, id, назначенный Preference в XML, не используется, когда Preference генерирует его View.)

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

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

Единственность id s

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

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

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

Динамическое создание представлений и присвоение id s

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

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

Если вы решите сохранить ссылки на свои представления вокруг, обязательно создайте их с помощью getApplicationContext() и обязательно установите для каждой ссылки значение null в 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 и один из наших новых 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);

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

Ответ 2

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

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

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

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

Кредиты на этот ответ.

Ответ 3

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