The LayoutInflater.inflate
dokumentasi tidak persis jelas kepada saya tentang tujuan dari attachToRoot
parameter.
attachToRoot : apakah hirarki yang meningkat harus dilampirkan ke parameter root? Jika false, root hanya digunakan untuk membuat subclass LayoutParams yang benar untuk tampilan root dalam XML.
Bisakah seseorang tolong jelaskan secara lebih rinci, khususnya apa tampilan root, dan mungkin menunjukkan contoh perubahan perilaku antara true
dan false
nilai - nilai?
android
android-layout
android-view
layout-inflater
Jeff Axelrod
sumber
sumber
Jawaban:
SEKARANG ATAU TIDAK SEKARANG
Perbedaan utama antara parameter "ketiga" attachToRoot menjadi benar atau salah adalah ini.
true: tambahkan tampilan anak ke orangtua KANAN SEKARANG
palsu: tambahkan tampilan anak ke orangtua TIDAK SEKARANG .
Tambahkan nanti. `
Itu nanti ketika Anda menggunakan misalnya
parent.addView(childView)
Kesalahpahaman yang umum adalah, jika parameter attachToRoot salah maka tampilan anak tidak akan ditambahkan ke induk. SALAH
Dalam kedua kasus, tampilan anak akan ditambahkan ke parentView. Hanya masalah waktu .
setara dengan
A NO-NO BESAR
Anda seharusnya tidak pernah meneruskan attachToRoot sebagai true ketika Anda tidak bertanggung jawab untuk menambahkan tampilan anak ke orang tua.
Misalnya Saat menambahkan Fragmen
jika Anda melewatkan parameter ketiga sebagai true, Anda akan mendapatkan IllegalStateException karena orang ini.
Karena Anda telah menambahkan fragmen anak di onCreateView () karena kesalahan. Memanggil tambah akan memberi tahu Anda bahwa tampilan anak sudah ditambahkan ke induk karenanya IllegalStateException .
Di sini Anda tidak bertanggung jawab untuk menambahkan childView, FragmentManager bertanggung jawab. Jadi selalu salah dalam kasus ini.
CATATAN: Saya juga membaca bahwa parentView tidak akan mendapatkan childView touchEvents jika attachToRoot salah. Tapi saya belum mengujinya.
sumber
FragmentManager
, terima kasih!Jika disetel ke true maka ketika tata letak Anda meningkat itu akan secara otomatis ditambahkan ke hierarki tampilan dari ViewGroup yang ditentukan dalam parameter ke-2 sebagai anak. Misalnya jika parameter root adalah a
LinearLayout
maka tampilan Anda yang meningkat akan secara otomatis ditambahkan sebagai anak dari tampilan itu.Jika disetel ke false maka tata letak Anda akan meningkat tetapi tidak akan dilampirkan ke tata letak lainnya (sehingga tidak akan ditarik, menerima acara sentuh dll).
sumber
false
untukattachToRoot
selama saya Fragmen inionCreateView
. Ini memecahkan masalah dan belum tata letak fragmen ini terlihat dan aktif, meskipun jawaban Anda. Apa yang terjadi di sini?true
, tampilan dilampirkan ke parameter 2 yang merupakancontainer
, tetapi kemudian Anda mengatakan fragmen secara otomatis dilampirkanonCreateView()
, jadi menurut pemahaman saya, parameter ketiga tidak berguna dan harus diaturfalse
selalu?onCreateView
. Jika Anda mengembang tata letak lebih lanjut ke tampilan root itu, atau Anda menggembungkan dalam konteks yang berbeda (misalnya dalam suatu Kegiatan) maka itu berguna.Sepertinya banyak teks dalam tanggapan tetapi tidak ada kode, itu sebabnya saya memutuskan untuk menghidupkan kembali pertanyaan lama ini dengan contoh kode, dalam beberapa tanggapan yang disebutkan orang:
Apa yang sebenarnya berarti dalam kode (apa yang dipahami sebagian besar programmer) adalah:
Perhatikan bahwa kode sebelumnya adalah menambahkan tata letak
R.layout.child_view
sebagai anakMyCustomLayout
karenaattachToRoot
param adalahtrue
dan penerima params tata letak induk persis dengan cara yang sama seperti jika saya akan menggunakanaddView
pemrograman, atau seolah-olah saya melakukan ini di xml:Kode berikut menjelaskan skenario ketika dilewatkan
attachRoot
sebagaifalse
:Dalam kode sebelumnya Anda tentukan yang Anda inginkan
myView
menjadi objek root sendiri dan tidak melampirkannya ke orangtua mana pun, kemudian kami menambahkannya sebagai bagian dariLinearLayout
tetapi untuk sesaat itu adalah tampilan yang berdiri sendiri (tanpa orangtua).Hal yang sama terjadi dengan Fragmen, Anda dapat menambahkannya ke grup yang sudah ada dan menjadi bagian darinya, atau hanya meneruskan parameter:
Untuk menentukan bahwa itu akan menjadi root sendiri.
sumber
Dokumentasi dan dua jawaban sebelumnya seharusnya cukup, hanya beberapa pemikiran dari saya.
The
inflate
metode yang digunakan untuk mengembang file layout. Dengan tata letak yang meningkat itu Anda harus kemungkinan untuk melampirkannya langsung ke indukViewGroup
atau hanya mengembang hierarki tampilan dari file tata letak itu dan bekerja dengannya di luar hierarki tampilan normal.Dalam kasus pertama
attachToRoot
parameter harus disetel ketrue
(atau lebih sederhana menggunakaninflate
metode yang mengambil file tata letak dan root indukViewGroup
(bukannull
)). Dalam hal ini yangView
dikembalikan hanyalahViewGroup
yang dilewatkan dalam metode,ViewGroup
yang akan ditambahkan hierarki tampilan.Untuk opsi kedua yang dikembalikan
View
adalah rootViewGroup
dari file layout. Jika Anda ingat diskusi terakhir kami dariinclude-merge
pertanyaan pasangan, ini adalah salah satu alasan untukmerge
pembatasan (ketika file tata letak denganmerge
sebagai root meningkat, Anda harus menyediakan orangtua danattachedToRoot
harus diatur ketrue
). Jika Anda memiliki file tata letak denganmerge
tag root danattachedToRoot
diatur kefalse
makainflate
metode tidak akan kembali karenamerge
tidak memiliki yang setara. Juga, seperti kata dokumentasi,inflate
versi denganattachToRoot
set kefalse
penting karena Anda dapat membuat tampilan hierarki dengan benarLayoutParams
dari orang tua. Ini penting dalam beberapa kasus, yang paling terkenal pada anak-anak dariAdapterView
, subkelas dariViewGroup
, yangaddView()
metode yang ditetapkan tidak didukung. Saya yakin Anda ingat menggunakan baris ini dalamgetView()
metode:Baris ini memastikan bahwa
R.layout.row_layout
file yang digelembungkan memiliki yang benarLayoutParams
dariAdapterView
subkelas yang ditetapkan pada akarnyaViewGroup
. Jika Anda tidak akan melakukan ini, Anda dapat memiliki beberapa masalah dengan file tata letak jika root adalah aRelativeLayout
. TheTableLayout/TableRow
juga memiliki beberapa khusus dan pentingLayoutParams
dan Anda harus memastikan pandangan di dalamnya memiliki yang benarLayoutParams
.sumber
Saya sendiri juga bingung tentang apa tujuan sebenarnya dari
attachToRoot
dalaminflate
metode. Setelah sedikit belajar UI, saya akhirnya mendapatkan jawabannya:induk:
dalam hal ini adalah widget / tata letak yang mengelilingi objek tampilan yang ingin Anda kembangkan menggunakan findViewById ().
attachToRoot:
melampirkan pandangan ke orang tua mereka (termasuk mereka dalam hierarki induk), sehingga setiap acara sentuh yang menerima pandangan juga akan ditransfer ke tampilan orang tua. Sekarang terserah orang tua apakah ingin menghibur acara-acara itu atau mengabaikannya. jika disetel ke false, mereka tidak ditambahkan sebagai anak-anak langsung dari orang tua dan orang tua tidak menerima acara sentuhan apa pun dari tampilan.
Semoga ini bisa menghilangkan kebingungan
sumber
Saya menulis jawaban ini karena bahkan setelah melewati beberapa halaman StackOverflow saya tidak dapat memahami dengan jelas apa arti attachToRoot. Di bawah ini adalah metode mengembang () di kelas LayoutInflater.
Lihatlah file activity_main.xml , tata letak button.xml dan file MainActivity.java yang saya buat.
activity_main.xml
button.xml
MainActivity.java
Saat kami menjalankan kode, kami tidak akan melihat tombol di tata letak. Ini karena tata letak tombol kami tidak ditambahkan ke tata letak aktivitas utama karena attachToRoot disetel ke false.
LinearLayout memiliki metode addView (View view) yang dapat digunakan untuk menambahkan Views ke LinearLayout. Ini akan menambahkan tata letak tombol ke tata letak aktivitas utama, dan membuat tombol terlihat ketika Anda menjalankan kode.
Mari kita hapus baris sebelumnya, dan lihat apa yang terjadi ketika kita menetapkan attachToRoot sebagai true.
Sekali lagi kita melihat bahwa tata letak tombol terlihat. Ini karena attachToRoot secara langsung melampirkan tata letak yang meningkat ke induk yang ditentukan. Yang dalam hal ini adalah root LinearLayout. Di sini kita tidak perlu menambahkan view secara manual seperti yang kita lakukan pada kasus sebelumnya dengan metode addView (View view).
Mengapa orang mendapatkan IllegalStateException ketika mengatur attachToRoot sebagai true untuk sebuah Fragmen.
Ini karena untuk sebuah fragmen Anda telah menentukan di mana harus meletakkan tata letak fragmen Anda di file aktivitas Anda.
The add (int orangtua, Fragmen fragmen) menambahkan fragmen yang memiliki tata letak itu ke tata letak induk. Jika kami menetapkan attachToRoot sebagai true, Anda akan mendapatkan IllegalStateException: Anak yang ditentukan sudah memiliki orangtua. Karena tata letak fragmen sudah ditambahkan ke tata letak induk dalam metode add ().
Anda harus selalu memberikan false untuk attachToRoot ketika Anda menggembungkan Fragmen. Adalah tugas FragmentManager untuk menambah, menghapus, dan mengganti Fragmen.
Kembali ke contoh saya. Bagaimana jika kita melakukan keduanya.
Di baris pertama, LayoutInflater melampirkan tata letak tombol ke tata letak akar dan mengembalikan objek tampilan yang memegang tata letak tombol yang sama. Di baris kedua, kita menambahkan objek View yang sama ke tata letak root induk. Ini menghasilkan IllegalStateException yang sama yang kami lihat dengan Fragmen (Anak yang ditentukan sudah memiliki orangtua).
Perlu diingat bahwa ada metode inflate () kelebihan beban lainnya, yang menetapkan attachToRoot sebagai true secara default.
sumber
Ada banyak kebingungan tentang topik ini karena dokumentasi untuk metode inflate ().
Secara umum, jika attachToRoot disetel ke true, maka file tata letak yang ditentukan dalam parameter pertama meningkat dan dilampirkan ke ViewGroup yang ditentukan dalam parameter kedua pada saat itu. Ketika attachToRoot salah, file tata letak dari parameter pertama meningkat dan dikembalikan sebagai tampilan dan lampiran tampilan apa pun terjadi di lain waktu.
Ini mungkin tidak banyak berarti kecuali Anda melihat banyak contoh. Saat memanggil LayoutInflater.inflate () di dalam metode onCreateView dari sebuah Fragmen, Anda ingin memberikan false untuk attachToRoot karena Aktivitas yang terkait dengan Fragment tersebut sebenarnya bertanggung jawab untuk menambahkan tampilan Fragment tersebut. Jika Anda menggembungkan secara manual dan menambahkan tampilan ke tampilan lain di beberapa titik waktu kemudian, seperti dengan metode addView (), Anda akan ingin memberikan false untuk attachToRoot karena lampiran datang pada titik waktu berikutnya.
Anda dapat membaca tentang beberapa contoh unik lainnya tentang Dialog dan Tampilan kustom pada posting blog yang saya tulis tentang topik ini.
https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/
sumber
attachToRoot
disetel ke true berartiinflatedView
akan ditambahkan ke hierarki tampilan induk. Dengan demikian mungkin dapat "dilihat" dan merasakan peristiwa sentuhan (atau operasi UI lainnya) oleh pengguna. Jika tidak, itu baru saja dibuat, tidak ditambahkan ke hierarki tampilan apa pun dan dengan demikian tidak dapat dilihat atau menangani acara sentuh.Untuk pengembang iOS yang baru mengenal Android,
attachToRoot
setel ke true berarti Anda memanggil metode ini:Jika melangkah lebih jauh Anda mungkin bertanya: Mengapa saya harus melewati tampilan orang tua jika saya set
attachToRoot
kefalse
? Itu karena elemen root di pohon XML Anda memerlukan tampilan induk untuk menghitung beberapa LayoutParams (seperti induk pertandingan).sumber
Saat Anda menentukan induknya, attachToRoot menentukan apakah Anda ingin inflater melampirkannya pada induknya atau tidak. Dalam beberapa kasus ini menyebabkan masalah, seperti dalam ListAdapter itu akan menyebabkan pengecualian karena daftar mencoba untuk menambahkan tampilan ke daftar tetapi dikatakan sudah terlampir. Di tempat lain di mana Anda hanya menggembungkan tampilan sendiri untuk ditambahkan ke suatu Kegiatan, itu bisa berguna dan menghemat satu baris kode.
sumber
Misalnya kita memiliki
ImageView
, a,LinearLayout
dan aRelativeLayout
. LinearLayout adalah anak dari RelativeLayout. Hirarki Lihat akan.dan kami memiliki file tata letak terpisah untuk ImageView
image_view_layout.xml
Lampirkan ke root:
setImageResource(R.drawable.np);
dari ImageView Anda harus menemukannya dengan referensi dari induk yaituview.findById()
Tidak dilampirkan ke root:
view.setImageResource(R.drawable.np);
tanpa referensi wasitfindViewById
. Tapi container ditentukan sehingga ImageView mendapatkan LayoutParams dari container sehingga Anda bisa mengatakan bahwa referensi container hanya untuk LayoutParams.sumber
aturToRoot Setel ke true:
Bayangkan kita menentukan tombol dalam file tata letak XML dengan lebar tata letak dan tinggi tata letak diatur ke match_parent.
Kami sekarang ingin secara terprogram menambahkan Tombol ini ke dalam LinearLayout di dalam Fragmen atau Aktivitas. Jika LinearLayout kami sudah menjadi variabel anggota, mLinearLayout, kami cukup menambahkan tombol dengan yang berikut:
Kami menetapkan bahwa kami ingin mengembang Tombol dari file sumber daya tata letaknya; kami kemudian memberi tahu LayoutInflater bahwa kami ingin melampirkannya ke mLinearLayout. Parameter tata letak kami merasa terhormat karena kami tahu Tombol akan ditambahkan ke LinearLayout. Jenis params tata letak Button harus LinearLayout.LayoutParams.
attachToRoot Set ke false (tidak diharuskan untuk menggunakan false)
Mari kita lihat kapan Anda ingin mengatur attachToRoot menjadi false. Dalam skenario ini, Lihat ditentukan dalam parameter pertama mengembang () tidak terlampir ke ViewGroup di parameter kedua pada saat ini dalam waktu.
Ingat contoh Tombol kami dari sebelumnya, di mana kami ingin melampirkan Tombol khusus dari file tata letak ke mLinearLayout. Kami masih dapat melampirkan Tombol kami ke mLinearLayout dengan mengirimkan false untuk attachToRoot — kami baru saja menambahkannya sendiri secara manual sesudahnya.
Kedua baris kode ini setara dengan apa yang kami tulis sebelumnya dalam satu baris kode ketika kami memberikan true untuk attachToRoot. Dengan memberikan false, kami mengatakan bahwa kami tidak ingin melampirkan View kami ke root ViewGroup dulu. Kami mengatakan bahwa itu akan terjadi di beberapa titik waktu lain. Dalam contoh ini, titik waktu lainnya hanyalah metode addView () yang digunakan tepat di bawah inflasi.
Contoh attachToRoot palsu membutuhkan sedikit lebih banyak pekerjaan ketika kita secara manual menambahkan tampilan ke ViewGroup.
attachToRoot Setel ke false (false Wajib)
Saat menggembungkan dan mengembalikan Tampilan Fragmen di onCreateView (), pastikan Anda memberikan false untuk attachToRoot. Jika Anda meneruskan dengan benar, Anda akan mendapatkan IllegalStateException karena anak yang ditentukan sudah memiliki orangtua. Anda harus menentukan di mana tampilan Fragmen Anda akan ditempatkan kembali di Aktivitas Anda. Adalah tugas FragmentManager untuk menambah, menghapus, dan mengganti Fragmen.
Wadah root_viewGroup yang akan menampung Fragmen Anda di Aktivitas Anda adalah parameter ViewGroup yang diberikan kepada Anda di onCreateView () di Fragment Anda. Ini juga merupakan ViewGroup yang Anda berikan ke LayoutInflater.inflate (). FragmentManager akan menangani melampirkan View Fragment Anda ke ViewGroup ini. Anda tidak ingin melampirkannya dua kali. Setel attachToRoot ke false.
Mengapa kita diberi ViewGroup induk Fragment kami di tempat pertama jika kita tidak ingin melampirkannya di onCreateView ()? Mengapa metode mengembang () meminta ViewGroup root?
Ternyata bahkan ketika kita tidak segera menambahkan Tampilan kami yang baru meningkat ke ViewGroup induknya, kita masih harus menggunakan LayoutParams induk agar View baru untuk menentukan ukuran dan posisinya kapan pun akhirnya terpasang.
Tautan: https://youtu.be/1Y0LlmTCOkM?t=409
sumber
Hanya berbagi beberapa poin yang saya temui saat mengerjakan topik ini,
Selain jawaban yang diterima saya ingin beberapa poin yang dapat membantu.
Jadi, ketika saya menggunakan attachToRoot sebagai true, tampilan yang dikembalikan adalah tipe ViewGroup yaitu root ViewGroup induk yang dilewatkan sebagai parameter untuk metode mengembang (layoutResource, ViewGroup, attachToRoot) , bukan jenis tata letak yang dilewatkan tetapi pada attachToRoot sebagai false kita mendapatkan tipe fungsi pengembalian ViewGroup root layoutResource itu .
Izinkan saya menjelaskan dengan sebuah contoh:
Jika kita memiliki LinearLayout sebagai tata letak root dan kemudian kita ingin menambahkan TextView di dalamnya melalui fungsi mengembang .
kemudian menggunakan attachToRoot sebagai benar fungsi mengembang mengembalikan View jenis LinearLayout
saat menggunakan attachToRoot sebagai fungsi semburan palsu mengembalikan Tampilan tipe TextView
Semoga temuan ini dapat membantu ...
sumber