Bir görünüme programlı olarak nasıl kimlik atayabilirim?


202

XML dosyasında, bir görünüme bir kimlik atayabilir android:id="@+id/something"ve sonra arayabiliriz findViewById(), ancak programlı bir görünüm oluştururken nasıl bir kimlik atayabilirim?

Bence setId()varsayılan görevle aynı değil. setId()ekstradır.

Beni kimse düzeltebilir mi?


Yanıtlar:


521

Android'e idgenel bakış

Android id, görünümleri tanımlamak için yaygın olarak kullanılan bir tamsayıdır; Bu idXML (mümkün) ve kodu aracılığıyla yoluyla tayin edilebilir (programlı.) idXML ile belirlenen bir referans almak için en yararlı olan Viewlar bir tarafından üretilen Inflater(örneğin, kullanılmasıyla olduğu gibi setContentView.)

Ata idüzeriXML

  • Bir özellik ekle android:id="@+id/SomeName "görünümünüze.
  • Uygulamanız oluşturulduğunda, kodda kullanılmak üzere benzersizandroid:id bir atanır . int
  • Sizin referans android:id'ın int'kullanarak kod değeri R.id.somename'(etkili sabiti.)
  • Bu intyapı dan sürüme değişebilir böylece bir kimliği kopyalamak asla gelen gen/package.name/ R.javasadece "kullanın R.id.somename".
  • (Ayrıca, XML'de a'ya idatanmış bir URL oluşturulurken Preferencekullanılmaz .)PreferenceView

Kodla ata id(programlı olarak)

  • İnt idkullanarak manuel olarak ayarlamasomeView.setId();
  • intPozitif olmalıdır, ancak aksi takdirde ne istersen olabilir arbitrary- (bu korkutucu ise okumaya devam.)
  • Örneğin, öğeleri temsil eden birkaç görünüm oluşturuyor ve numaralandırıyorsanız, öğe numaralarını kullanabilirsiniz.

Tekliği ids

  • XMLatanan ids benzersiz olacaktır.
  • Kod atanan idler do not benzersiz olmak zorunda
  • Kod atanan ids (teorik olarak) atanmış s ile XMLçakışabilir id.
  • Bu çelişkiler iddoğru sorgulandığında önemli olmayacaktır (okumaya devam edin) .

Çatışmanın idne zaman (ve neden) önemli olmadığı

  • findViewById(int)belirttiğiniz Görünüm'deki görünüm hiyerarşisi içinde önce derinlik yinelemesini yineleyecek ve Viewbulduğu ilk eşlemeyi döndürecektir id.
  • Hiyerarşide idXML tanımlı bir koddan önce atanmış kod atanmamışlar olmadığı sürece , XML tanımlı Görünümü her zaman döndürür 'd.idfindViewById(R.id.somename)id

Dinamik Görüntüleme ve Atama oluşturma IDs

  • XML düzeninde ViewGroupile bir boş tanımlayın id.
  • Bir Bu gibi LinearLayoutolan android:id="@+id/placeholder".
  • Yer tutucuyu s ViewGroupile doldurmak için kodu kullanın View.
  • İhtiyacınız varsa veya istiyorsanız, idher görünüme uygun olanları atayın .
  • Bu alt görünümleri placeholder.findViewById (convenientInt) kullanarak sorgulayın;

  • View.generateViewId()Benzersiz bir kimlik oluşturmanıza olanak tanıyan API 17 tanıtıldı .

Görüşlerinizle ilgili referansları tutmayı seçerseniz , bunları somutlaştırdığınızdan getApplicationContext()ve her referansı null değerine ayarladığınızdan emin olun onDestroy. Görünüşe göre sızıntıActivity (o sonra yok edilir üzerine asılı) savurganlıktır .. :)

Kodda android:idkullanmak için XML ayırma

View.generateViewId() Benzersiz bir kimlik oluşturan API 17 tanıtıldı . (Bunu belirtmek için şans-değişiklik-değişiklikleri sayesinde.) *

Senin Eğer ViewGroupkutu XML üzerinden tanımlanamaz (veya siz olmak istemiyorum) bunun eşsiz kalmasını sağlamak için XML üzerinden id ayırabilir:

Burada, değerleri / ids.xml bir özel tanımlar id:

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

Ardından ViewGroup veya View oluşturulduktan sonra özel kimliği ekleyebilirsiniz

myViewGroup.setId(R.id.reservedNamedId);

Çelişkili idörnek

Şaşırtıcı bir örnekle netlik için id, sahne arkasında bir çatışma olduğunda neler olduğunu inceleyelim .

düzen / 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>

Bir çatışmayı simüle etmek için, en son derlememize R.id.placeholder( @+id/placeholder) intdeğeri atadığını söyleyelim 12 .

Daha sonra, MyActivity.java program aracılığıyla bazı ekler görünümleri tanımlar (kod aracılığıyla):

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

Yani placeholder, yeni TextViewslarımızdan idbirinde 12 tane var! Ancak, yer tutucunun alt görünümlerini sorgularsak bu gerçekten sorun olmaz:

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

*O kadar kötü değil


9
Buna ek olarak, benzer çözümleri kodlayan birinin API> 17'deki çakışmayan kimlikler için View.generateViewId () öğesinin farkında olması yararlı olabilir
AllDayAmazing

Not findViewById"Sürece hiyerarşisinde bir XML tanımlı id yukarıda atanmış bir kod atanmış kimlikleri olduğu gibi" öylesine bir derinlik ilk keşif yapar teknik olarak doğru değildir; "yukarıda" yerine "önce" dir.
Karu

Android geliştirici araçlarının daha yeni sürümlerinde, kimliğin programlı olarak rastgele bir değere ayarlanması derleyici hatası olarak işaretlenir. Değerin gerçek bir kaynak kimliği olması bekleniyor.
ThomasW

Buna beş yıl önce cevap verdiğimde bile böyle olduğunu düşünüyorum - bu yüzden özel kimliklerin tanımlanması gerekiyordu ids.xml. Gerçekten keyfi kimlikler için View.generateViewId()(API 17) kullanın . (Lütfen kaçırırsam noktanızı açıklığa kavuşturun.)
CodeShane

> (Ayrıca, Tercih Görünümünü oluşturduğunda XML'de bir Tercih'e atanan bir kimlik kullanılmaz.) Bununla çok ilgili. Benim kod miras gelen PreferenceDialogFragmentCompatkimlikler R.idolanlar görünüm hiyerarşisi ile eşleşmiyor gibi görünüyor . Bu şekilde görünümü kimliğe göre bulamıyorum.
UrK

6

Bunun için sadece kullanabilirsiniz View.setId(integer). XML'de, bir String kimliği ayarlamış olsanız bile, bu bir tam sayıya dönüştürülür. Bu nedenle, Views programlı olarak eklediğiniz herhangi bir (pozitif) Tamsayı kullanabilirsiniz .

ViewBelgelere göre

Tanımlayıcının bu görünümün hiyerarşisinde benzersiz olması gerekmez. Tanımlayıcı pozitif bir sayı olmalıdır.

Bu nedenle, istediğiniz herhangi bir pozitif tamsayıyı kullanabilirsiniz, ancak bu durumda eşdeğer kimliklere sahip bazı görünümler olabilir. Hiyerarşi içinde bazı görünümleri aramak istiyorsanız, bazı önemli nesnelerle setTag çağrısını yapmak kullanışlı olabilir.

Bu cevaba verilen krediler .


5

Evet, istediğiniz setId(value)herhangi bir (pozitif) tamsayı değeri olan herhangi bir görünümü çağırabilir ve daha sonra bunu kullanarak üst kapsayıcıda bulabilirsiniz findViewById(value). setId()Farklı kardeş görünümleri için aynı değerle çağrı yapmanın geçerli olduğunu , ancak findViewById()yalnızca ilkini döndüreceğini unutmayın.


1
Sıfırdan büyük bir tamsayı kullanmanız gerektiğini unutmayın.
Peter Ajtai

gerçi findViewById (int) adlı görünümü hiyerarşi yoluyla yinelemeli yineleme olacak belirttiğiniz ve bunun, eşleşen kimlikli bulduğu ilk Görünüm dönmek en doğrusudur 1 cevap belirtildi.
Aniket Thakur

Evet, findViewByIdbilinen bir ataya çağrı yapmak performans nedenleriyle iyi bir fikirdir, ancak doğru kimliğe sahip bir kişi varsa hemen bir çocuk bulacağını garanti etmez.
Karu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.