Jak mogę przypisać identyfikator do widoku programowo?

202

W pliku XML możemy przypisać identyfikator do widoku takiego jak, android:id="@+id/something"a następnie wywołać findViewById(), ale jak programowo utworzyć widok, jak przypisać identyfikator?

Myślę, że setId()to nie to samo, co domyślne przypisanie. setId()jest ekstra.

Czy ktoś może mnie poprawić?

DuyguK
źródło
1
Podzbiór: jak wygenerować unikalne identyfikatory: stackoverflow.com/questions/1714297/...
Ciro Santilli 2 冠状 病 六四 事件 法轮功

Odpowiedzi:

521

idOmówienie Androida

Android idto liczba całkowita powszechnie używana do identyfikacji widoków; to idmoże być przypisany przez XML (jeśli to możliwe) i za pośrednictwem kodu (programowe). Określenie idnajbardziej użyteczne dla uzyskania punktów odniesienia na XML zdefiniowane Viewa generowany przez Inflater(na przykład za pomocą setContentView).

Przypisz idprzezXML

  • Dodaj atrybut android:id="@+id/somename "do widzenia.
  • Po utworzeniu aplikacji android:idzostanie przypisany unikatowy int do użycia w kodzie.
  • Odwołać swój android:id„s intwartości w kodzie za pomocą« R.id.somename»(w praktyce stałą).
  • intmożna to zmienić z kompilacji na kompilację, więc nigdy nie kopiuj identyfikatora z gen/paczki.nazwa/ R.java, po prostu użyj „ R.id.somename”.
  • (Również idprzypisany do Preferencew XML nie jest używany, gdy jego Preferencegeneruje View.)

Przypisywanie idza pomocą kodu (programowo)

  • Ustaw ręcznie idza pomocą someView.setId(int);
  • To intmusi być pozytywne, ale poza tym jest arbitralne - może być czymkolwiek chcesz (czytaj dalej, jeśli to jest przerażające).
  • Na przykład, jeśli tworzysz i numerujesz kilka widoków reprezentujących elementy, możesz użyć ich numeru elementu.

Wyjątkowość ids

  • XML-przypisane ids będą unikalne.
  • Kod przypisany idów temat nie muszą być unikalne
  • Przypisane kodem ids (teoretycznie) mogą powodować konflikt z XMLprzypisanymi ids.
  • Te konflikty idnie będą miały znaczenia, jeśli zostaną poprawnie zapytane (czytaj dalej) .

Kiedy (i dlaczego) konflikty idnie mają znaczenia

  • findViewById(int)powtórzy rekursywnie najpierw głębokość przez hierarchię widoku z określonego widoku i zwróci pierwszą Viewznalezioną z pasującym id.
  • Tak długo, jak nie ma przypisanych kodów idprzypisanych przed XML zdefiniowanym idw hierarchii, findViewById(R.id.somename)zawsze zwróci widok zdefiniowany XML, więc id'd.

Dynamiczne tworzenie widoków i przypisywanie IDs

  • W układzie XML zdefiniuj puste za ViewGrouppomocą id.
  • Takich jak LinearLayoutz android:id="@+id/placeholder".
  • Użyć kodu, aby wypełnić zastępczy ViewGroupz Views.
  • Jeśli potrzebujesz lub chcesz, przypisz idte, które są wygodne dla każdego widoku.
  • Zapytaj o te widoki potomne za pomocą placeholder.findViewById (wygodnaInt);

  • Wprowadzono API 17, View.generateViewId()które pozwala wygenerować unikalny identyfikator.

Jeśli zdecydujesz się zachować odniesienia do swoich widoków , pamiętaj o ich utworzeniu getApplicationContext()i ustaw dla każdego odwołania wartość null onDestroy. Widocznie wycieka z Activity(wiszące na to po to jest zniszczone) jest marnotrawstwem .. :)

Zarezerwuj android:idkod XML do wykorzystania w kodzie

Wprowadzono API 17, View.generateViewId() który generuje unikalny identyfikator. (Dzięki zmianom szansy na dokonanie zmian za wskazanie tego.) *

Jeśli ViewGroupnie można go zdefiniować za pomocą XML (lub nie chcesz, aby tak było), możesz zarezerwować identyfikator za pomocą XML, aby upewnić się, że pozostaje unikalny:

Tutaj wartości / ids.xml definiują niestandardowe id:

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

Następnie po utworzeniu grupy ViewGroup lub View możesz dołączyć niestandardowy identyfikator

myViewGroup.setId(R.id.reservedNamedId);

Sprzeczny idprzykład

Dla jasności, jako zaciemniający przykład, przyjrzyjmy się, co dzieje się, gdy idza kulisami pojawia się konflikt.

layout / 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>

Aby zasymulować konflikt, powiedzmy, że nasz najnowszy kompilator przypisał R.id.placeholder( @+id/placeholder) intwartość 12 ..

Następnie MyActivity.java definiuje programowo niektóre widoki widoków (poprzez kod):

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

Tak więc placeholderi jedno z naszych nowych TextViewma idpo 12! Ale to nie jest tak naprawdę problem, jeśli zapytamy o widoki potomków osoby zastępczej:

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

*Nie tak źle

CodeShane
źródło
9
Oprócz tego może być przydatne dla kogoś, kto koduje podobne rozwiązania, zapoznanie się z funkcją View.generateViewId () w interfejsie API> 17 dla identyfikatorów bez konfliktu
AllDayAmazing
Zauważ, że przeprowadzane findViewByIdjest badanie głębokości, więc „Dopóki nie ma identyfikatorów przypisanych do kodu przypisanych powyżej identyfikatora zdefiniowanego w XML w hierarchii” nie jest technicznie poprawny; to „przed”, a nie „nad”.
Karu
W nowszych wersjach narzędzi programistycznych dla Androida programowe ustawienie identyfikatora na dowolną wartość zostanie oznaczone jako błąd kompilatora. Oczekuje się, że wartość będzie rzeczywistym identyfikatorem zasobu.
ThomasW
Wydaje mi się, że tak było nawet w przypadku, gdy odpowiedziałem na to pięć lat temu - właśnie dlatego musiał zostać zdefiniowany niestandardowy identyfikator ids.xml. Aby uzyskać naprawdę dowolne identyfikatory, użyj View.generateViewId()(API 17). (Proszę o wyjaśnienie, o ile mi tego brakowało).
CodeShane
> (Również identyfikator przypisany do Preferencji w XML nie jest używany, gdy Preferencje generują jego Widok.) Bardzo mnie to interesuje. Mój kod dziedziczy po PreferenceDialogFragmentCompatnim. Wygląda na to, że identyfikatory R.idnie pasują do hierarchii widoku. W ten sposób nie mogę znaleźć widoku według ID.
UrK
6

Możesz po prostu użyć View.setId(integer)do tego. W XML, nawet jeśli ustawiasz identyfikator ciągu, jest on konwertowany na liczbę całkowitą. Z tego powodu możesz użyć dowolnej (dodatniej) liczby całkowitej dla Views dodanego programowo.

Zgodnie z Viewdokumentacją

Identyfikator nie musi być unikalny w hierarchii tego widoku. Identyfikator powinien być liczbą dodatnią.

Możesz więc użyć dowolnej dodatniej liczby całkowitej, którą lubisz, ale w tym przypadku mogą istnieć niektóre widoki o równoważnych identyfikatorach. Jeśli chcesz wyszukać jakiś widok w hierarchii, może się przydać setTag z niektórymi kluczowymi obiektami.

Podziękowania dla tej odpowiedzi .

Sander van't Veer
źródło
5

Tak, można wywołać setId(value)w dowolnym widoku z dowolnego (pozytywnego) wartość całkowitą, która Ci się podoba, a następnie go znaleźć w kontenerze nadrzędnym użyciu findViewById(value). Zauważ, że prawidłowe jest wywoływanie setId()z tą samą wartością dla różnych widoków rodzeństwa, ale findViewById()zwróci tylko pierwszy.

skarbie
źródło
1
Pamiętaj, że musisz użyć liczby całkowitej większej niż zero.
Peter Ajtai,
chociaż findViewById (int) będzie iterował rekurencyjnie przez hierarchię widoków z określonego widoku i zwróci pierwszy znaleziony widok o pasującym identyfikatorze określonym w 1. odpowiedzi jest najbardziej dokładny.
Aniket Thakur
Tak, wzywanie findViewByIdznanego przodka jest dobrym pomysłem ze względu na wydajność, ale nie gwarantuje, że znajdzie natychmiastowe dziecko, jeśli jest takie z poprawnym identyfikatorem.
Karu