Bagaimana saya bisa menetapkan ID ke tampilan secara terprogram?

202

Dalam file XML, kita dapat menetapkan ID ke tampilan suka android:id="@+id/something"lalu panggil findViewById(), tetapi saat membuat tampilan secara pemrograman, bagaimana cara menetapkan ID?

Saya pikir setId()tidak sama dengan tugas standar. setId()tambahan.

Adakah yang bisa memperbaiki saya?

Duygu
sumber
1
Subset: cara membuat ID unik: stackoverflow.com/questions/1714297/…
Ciro Santilli “

Jawaban:

521

idIkhtisar Android

Android idadalah bilangan bulat yang biasa digunakan untuk mengidentifikasi tampilan; ini iddapat diberikan melalui XML (bila memungkinkan) dan melalui kode (terprogram.) Yang idpaling berguna untuk mendapatkan referensi untuk XML- Views yang dihasilkan oleh Inflater(misalnya dengan menggunakan setContentView.)

Tetapkan idmelaluiXML

  • Tambahkan atribut nama android:id="@+id/samaran "ke tampilan Anda.
  • Ketika aplikasi Anda dibangun, android:idakan diberi kode unik int untuk digunakan.
  • Referensi Anda android:id's intnilai dalam kode menggunakan "R.id. somename'(efektif konstan.)
  • ini intdapat berubah dari build ke build jadi jangan pernah menyalin id dari gen/package.name/ R.java, cukup gunakan "nama R.id.samaran".
  • (Juga, idditugaskan ke Preferencedalam XML tidak digunakan ketika Preferencemenghasilkan itu View.)

Tetapkan idmelalui kode (terprogram)

  • Set secara manual idmenggunakan ssomeView.setId( int);
  • Itu int harus positif, tetapi sebaliknya - itu bisa menjadi apa pun yang Anda inginkan (terus membaca jika ini menakutkan.)
  • Misalnya, jika membuat dan menomori beberapa tampilan yang mewakili item, Anda dapat menggunakan nomor itemnya.

Keunikan ids

  • XML-ditugaskan id akan menjadi unik.
  • Kode-ditugaskan ids tidak tidak harus unik
  • Kode yang ditugaskan iddapat (secara teoritis) bertentangan dengan XML-ditugaskan id.
  • idS yang saling bertentangan ini tidak masalah jika ditanya dengan benar (terus membaca) .

Kapan (dan mengapa) pertentangan idtidak masalah

  • findViewById(int)akan mengulangi kedalaman-pertama secara rekursif melalui hierarki tampilan dari tampilan yang Anda tentukan dan mengembalikan yang pertama Viewditemukannya dengan pencocokan id.
  • Selama tidak ada kode yang idditugaskan sebelum XML-didefinisikan iddalam hierarki, findViewById(R.id.somename)akan selalu mengembalikan XML-defined View jadi id.

Secara dinamis Membuat Tampilan dan Penugasan IDs

  • Dalam tata letak XML, tentukan kosong ViewGroupdengan id.
  • Seperti LinearLayoutdengan android:id="@+id/placeholder".
  • Gunakan kode untuk mengisi placeholder ViewGroupdengan View.
  • Jika Anda membutuhkan atau menginginkan, tetapkan apa saja idyang nyaman untuk setiap tampilan.
  • Query pandangan anak ini menggunakan placeholder.findViewById (convenientInt);

  • API 17 diperkenalkan View.generateViewId()yang memungkinkan Anda menghasilkan ID unik.

Jika Anda memilih untuk menyimpan referensi untuk pandangan Anda di sekitar , pastikan untuk instantiate dengan getApplicationContext()dan pastikan untuk mengatur setiap referensi menjadi nol onDestroy. Rupanya bocor yang Activity(menggantung ke atasnya setelah itu hancur) adalah boros .. :)

Cadangan XML android:iduntuk digunakan dalam kode

API 17 diperkenalkan View.generateViewId() yang menghasilkan ID unik. (Terima kasih telah mengambil kesempatan untuk melakukan perubahan karena menunjukkan ini.) *

Jika Anda ViewGrouptidak dapat didefinisikan melalui XML (atau Anda tidak menginginkannya), Anda dapat memesan id melalui XML untuk memastikannya tetap unik:

Di sini, nilai / ids.xml mendefinisikan sebuah kustom id:

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

Kemudian setelah ViewGroup atau View dibuat, Anda dapat melampirkan id khusus

myViewGroup.setId(R.id.reservedNamedId);

idContoh yang saling bertentangan

Untuk kejelasan dengan cara mengaburkan contoh, mari kita periksa apa yang terjadi ketika ada idkonflik di belakang layar.

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>

Untuk mensimulasikan konflik, katakanlah build terbaru kami menetapkan R.id.placeholder( @+id/placeholder) intnilai dari 12 ..

Selanjutnya, MyActivity.java mendefinisikan beberapa tampilan tambah secara terprogram (melalui kode):

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

Jadi placeholderdan salah satu dari kami yang baru TextViewmemiliki id12! Tapi ini sebenarnya bukan masalah jika kami meminta pandangan anak-anak placeholder:

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

*Tidak begitu buruk

CodeShane
sumber
9
Selain itu, mungkin berguna bagi seseorang dalam pengkodean solusi serupa untuk mengetahui tentang View.generateViewId () di API> 17 untuk ID yang tidak bertentangan
AllDayAmazing
Perhatikan bahwa findViewByIdmelakukan eksplorasi mendalam-pertama, jadi "Selama tidak ada id yang ditetapkan kode yang ditetapkan di atas id yang ditentukan XML dalam hierarki" secara teknis tidak benar; itu "sebelum" daripada "di atas".
Karu
Dalam versi yang lebih baru dari alat pengembang Android, secara terprogram mengatur ID ke nilai arbitrer akan ditandai sebagai kesalahan kompiler. Nilai tersebut diharapkan menjadi ID sumber daya aktual.
ThomasW
Saya percaya ini bahkan terjadi ketika saya menjawab ini lima tahun yang lalu - itu sebabnya id kustom telah didefinisikan dalam ids.xml. Untuk ID yang benar-benar arbitrer, gunakan View.generateViewId()(API 17). (Tolong jelaskan poin Anda jika saya melewatkannya.)
CodeShane
> (Juga, id yang ditetapkan untuk Preferensi dalam XML tidak digunakan ketika Preferensi menghasilkan Tampilannya.) Sangat tertarik tentang itu. Kode saya mewarisi dari PreferenceDialogFragmentCompatitu sepertinya id dari R.idtidak cocok dengan hierarki tampilan yang. Dengan cara ini saya tidak dapat menemukan tampilan dengan ID.
UrK
6

Anda bisa menggunakan View.setId(integer)ini untuk ini. Dalam XML, meskipun Anda sedang mengatur String id, ini akan dikonversi menjadi integer. Karena ini, Anda dapat menggunakan Integer (positif) apa pun untuk Views ditambahkan secara terprogram.

Menurut Viewdokumentasi

Pengidentifikasi tidak harus unik dalam hierarki tampilan ini. Pengidentifikasi harus berupa angka positif.

Jadi, Anda dapat menggunakan bilangan bulat positif apa pun yang Anda suka, tetapi dalam hal ini ada beberapa tampilan dengan id yang setara. Jika Anda ingin mencari beberapa tampilan dalam hierarki panggilan ke setTag dengan beberapa objek utama mungkin berguna.

Penghargaan untuk jawaban ini .

Sander van't Veer
sumber
5

Ya, Anda dapat memanggil setId(value)dalam tampilan apa pun dengan nilai integer (positif) apa pun yang Anda suka dan kemudian menemukannya di wadah induk menggunakan findViewById(value). Perhatikan bahwa valid untuk memanggil setId()dengan nilai yang sama untuk tampilan saudara yang berbeda, tetapi findViewById()hanya akan mengembalikan yang pertama.

dmon
sumber
1
Perhatikan bahwa Anda harus menggunakan bilangan bulat yang lebih besar dari nol.
Peter Ajtai
meskipun findViewById (int) akan beralih secara berulang melalui hierarki tampilan dari tampilan yang Anda tentukan dan mengembalikan tampilan pertama yang ditemukannya dengan id yang cocok yang ditentukan dalam jawaban pertama yang paling akurat.
Aniket Thakur
Ya, memanggil findViewByIdleluhur yang dikenal adalah ide yang bagus untuk alasan kinerja, tetapi tidak menjamin akan menemukan anak langsung jika ada satu dengan ID yang benar.
Karu