Saya agak bingung tentang peran forceLayout()
, requestLayout()
dan invalidate()
metode View
kelas.
Kapan mereka akan dipanggil?
android
android-layout
android-view
sdabet
sumber
sumber
TextView
. Saya pikir mungkin mereka ingin menggambarView
untuk yang terakhir kali sebelum mereka mengubah parameter yang berhubungan dengan tata letak, tetapi tidak benar-benar masuk akal jika kita berpikir tentang panggilan yang dipanggil dalam urutan yang berbeda (dan mereka memanggilinvalidate()
tepat setelahrequestLayout()
diTextView
demikian juga). Mungkin layak menerima pertanyaan lain tentang StackOverflow :)?invalidate()
danrequestLayout()
) dengan benar. Tujuan dari metode-metode tersebut adalah untuk mengetahuiView
jenis pembatalan seperti apa (sebagaimana Anda menyebutnya) telah terjadi. Ini tidak sepertiView
memutuskan jalan apa yang harus diikuti setelah Anda memanggil salah satu metode itu. Logika di balik memilihView
-lifecycle-path adalah memilih metode yang tepat untuk memanggil dirinya sendiri. Jika ada sesuatu yang berkaitan dengan perubahan ukuran -requestLayout()
harus dipanggil, jika hanya ada perubahan visual tanpa ukuran diubah - Anda harus meneleponinvalidate()
.View
dalam beberapa cara, misalnya Anda mendapatkan arusLayoutParams
dariView
dan Anda mengubah mereka, tetapi tidak menyebut baikrequestLayout
atausetLayoutParams
(yang panggilanrequestLayout
internal), maka Anda dapat menghubungiinvalidate()
sebanyak yang Anda inginkan, dan yangView
tidak akan melalui proses ukuran-layout, karena itu tidak akan mengubah ukurannya. Jika Anda tidak memberi tahu AndaView
bahwa ukurannya telah berubah (denganrequestLayout
pemanggilan metode), makaView
akan menganggap itu tidak, danonMeasure
danonLayout
tidak akan dipanggil.invalidate()
Panggilan
invalidate()
dilakukan saat Anda ingin menjadwalkan gambar ulang tampilan. Itu akan menghasilkanonDraw
dipanggil pada akhirnya (segera, tetapi tidak segera). Contoh kapan tampilan kustom menyebutnya adalah ketika properti teks atau warna latar belakang telah berubah.Tampilan akan digambar ulang tetapi ukurannya tidak akan berubah.
requestLayout()
Jika ada sesuatu tentang perubahan tampilan Anda yang akan mempengaruhi ukuran, maka Anda harus menelepon
requestLayout()
. Ini akan memicuonMeasure
danonLayout
tidak hanya untuk tampilan ini tetapi juga sepanjang garis untuk tampilan induk.Memanggil
requestLayout()
ini tidak dijamin hasil dalamonDraw
(bertentangan dengan apa yang diagram dalam jawaban diterima menyiratkan), sehingga biasanya dikombinasikan denganinvalidate()
.Contoh dari ini adalah ketika label kustom memiliki properti teksnya diubah. Label akan berubah ukuran dan karenanya perlu diukur ulang dan digambar ulang.
forceLayout()
Ketika ada
requestLayout()
yang dipanggil pada kelompok tampilan induk, itu tidak perlu untuk mengukur kembali dan menyampaikan pandangan anaknya. Namun, jika seorang anak harus dimasukkan dalam remeasure dan relayout, maka Anda dapat memanggilnyaforceLayout()
.forceLayout()
hanya bekerja pada anak jika itu terjadi bersamaan denganrequestLayout()
pada orangtua langsungnya. MemanggilforceLayout()
dengan sendirinya tidak akan berpengaruh karena tidak memicurequestLayout()
pohon tampilan.Baca Tanya Jawab ini untuk deskripsi yang lebih terperinci tentang
forceLayout()
.Pelajaran lanjutan
View
Kode sumbersumber
requestLayout()
sebelumnyainvalidate()
jika mau. Tidak ada yang melakukan tata letak atau menggambar segera. Sebaliknya, mereka menetapkan bendera yang pada akhirnya akan menghasilkan relayout dan redraw.Di sini Anda dapat menemukan beberapa respons: http://developer.android.com/guide/topics/ui/how-android-draws.html
Bagi saya panggilan untuk
invalidate()
hanya menyegarkan tampilan dan panggilan untukrequestLayout()
menyegarkan tampilan dan menghitung ukuran tampilan di layar.sumber
Anda menggunakan invalidate () pada tampilan yang ingin Anda redraw, itu akan membuat onDraw (Canvas c) untuk dipanggil, dan requestLayout () akan membuat rendering seluruh layout (fase pengukuran dan fase positioning) berjalan kembali. Anda harus menggunakannya jika Anda mengubah ukuran tampilan anak saat runtime tetapi hanya dalam kasus-kasus tertentu seperti batasan dari tampilan induk (maksud saya bahwa tinggi atau lebar orangtua adalah WRAP_CONTENT dan karenanya cocok mengukur anak-anak sebelum mereka dapat membungkusnya lagi)
sumber
Jawaban ini tidak benar tentang
forceLayout()
.Seperti yang dapat Anda lihat dalam kode
forceLayout()
itu hanya menandai pandangan sebagai "membutuhkan relayout" tetapi tidak menjadwalkan atau memicu relayout itu. Relai tidak akan terjadi sampai pada suatu titik di masa depan orang tua tampilan diletakkan karena alasan lain.Ada juga masalah yang jauh lebih besar saat menggunakan
forceLayout()
danrequestLayout()
:Katakanlah Anda telah meminta
forceLayout()
tampilan. Sekarang ketika memanggilrequestLayout()
keturunan dari pandangan itu, Android akan secara rekursif memanggilrequestLayout()
leluhur keturunan itu. Masalahnya adalah itu akan menghentikan rekursi pada tampilan yang Anda panggilforceLayout()
. JadirequestLayout()
panggilan tidak akan pernah mencapai view root dan dengan demikian tidak pernah menjadwalkan lulus tata letak. Seluruh subtree dari hierarki tampilan sedang menunggu tata letak dan memanggilrequestLayout()
semua tampilan subtree tersebut tidak akan menyebabkan tata letak. Hanya memanggilrequestLayout()
sembarang tampilan di luar subtree yang akan memecah mantra.Saya akan mempertimbangkan implementasi
forceLayout()
(dan bagaimana pengaruhnyarequestLayout()
rusak dan Anda seharusnya tidak pernah menggunakan fungsi itu dalam kode Anda.sumber
View
dan dengan menjalankan sendiri masalah tersebut & men-debug-nya.forceLayout()
API: itu tidak benar-benar memaksa pass layout, melainkan hanya mengubah flag yang sedang diamationMeasure()
, tetapionMeasure()
tidak akan dipanggil kecualirequestLayout()
atau secara eksplisitView#measure()
dipanggil. Itu berarti, ituforceLayout()
harus dipasangkanrequestLayout()
. Di sisi lain, mengapa kemudian melakukanforceLayout()
jika saya masih perlu melakukanrequestLayout()
?requestLayout()
melakukan segala sesuatu yangforceLayout()
juga dilakukannya.forceLayout
masuk akal. Jadi pada akhirnya nama dan dokumentasinya sangat buruk.invalidate()
--->onDraw()
dari utas UIpostInvalidate()
--->onDraw()
dari utas latar belakangrequestLayout()
--->onMeasure()
danonLayout()
DAN TIDAKonDraw()
forceLayout()
--->onMeasure()
danonLayout()
HANYA JIKA induk langsung dipanggilrequestLayout()
.sumber