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ć?


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


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 .


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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.