Saya tidak berbicara tentang properti bingkai, karena dari itu Anda hanya bisa mendapatkan ukuran tampilan di xib. Saya berbicara tentang kapan tampilan diubah ukurannya karena batasannya (mungkin setelah rotasi, atau sebagai respons terhadap suatu peristiwa). Apakah ada cara untuk mengetahui lebar dan tinggi saat ini?
Saya mencoba iterasi melalui batasannya mencari batasan lebar dan tinggi, tetapi itu tidak terlalu bersih dan gagal ketika ada batasan intrinsik (karena saya tidak dapat membedakan keduanya). Selain itu, ini hanya berfungsi jika mereka benar-benar memiliki batasan lebar dan tinggi, yang tidak akan berfungsi jika mereka bergantung pada batasan lain untuk mengubah ukurannya.
Mengapa ini sangat sulit bagi saya. ARG!
ios
autolayout
yuf
sumber
sumber
Jawaban:
Jawabannya adalah
[view layoutIfNeeded]
.Inilah alasannya:
Anda masih mendapatkan lebar dan tinggi tampilan saat ini dengan memeriksa
view.bounds.size.width
danview.bounds.size.height
(atau bingkai, yang setara kecuali Anda bermain-main denganview.transform
).Jika yang Anda inginkan adalah lebar dan tinggi yang disiratkan oleh batasan yang ada, jawabannya bukanlah memeriksa batasan secara manual, karena itu akan mengharuskan Anda untuk menerapkan ulang seluruh logika penyelesaian batasan dari sistem tata letak otomatis untuk menafsirkannya. kendala. Alih-alih, yang harus Anda lakukan hanyalah meminta tata letak otomatis untuk memperbarui tata letak itu , sehingga ini memecahkan batasan dan memperbarui nilai view.bounds dengan solusi yang benar, lalu Anda memeriksa view.bounds.
Bagaimana Anda meminta tata letak otomatis untuk memperbarui tata letak? Panggil
[view setNeedsLayout]
jika Anda ingin tata letak otomatis memperbarui tata letak pada putaran berikutnya dari putaran proses.Namun, jika Anda ingin segera memperbarui tata letak, sehingga Anda dapat segera mengakses nilai batas baru nanti dalam fungsi Anda saat ini, atau di titik lain sebelum pergantian putaran proses, Anda perlu memanggil
[view setNeedsLayout]
dan[view layoutIfNeeded]
.Anda mengajukan pertanyaan kedua: "bagaimana saya bisa mengubah batasan tinggi / lebar jika saya tidak memiliki referensi ke sana secara langsung?".
Jika Anda membuat batasan di IB, solusi terbaik adalah membuat IBOutlet di pengontrol tampilan atau tampilan Anda sehingga Anda memiliki referensi langsung ke sana. Jika Anda membuat batasan dalam kode, maka Anda harus menyimpan referensi di properti internal weak pada saat Anda membuatnya. Jika orang lain yang membuat batasan, Anda perlu menemukannya dengan memeriksa properti memeriksa view.constraints pada tampilan, dan mungkin seluruh hierarki tampilan, serta menerapkan logika yang menemukan NSLayoutConstraint yang penting. Ini mungkin cara yang salah, karena ini juga secara efektif mengharuskan Anda untuk menentukan kendala tertentu yang menentukan ukuran batas, ketika tidak ada jaminan untuk menjadi jawaban sederhana untuk pertanyaan itu. Nilai batas akhir bisa menjadi solusi untuk sistem yang sangat rumit dengan banyak kendala,
sumber
layoutIfNeeded
bagus, dan akan segera membuat bingkai tersedia. Namun, ini juga akan memaksa rendering batasan pada semua tampilan di sub-hierarki tampilan tempat ia dipanggil. Jika Anda menambahkan tampilan secara terprogram, misalnya, dan memanggillayoutIfNeeded
semuanya dalam rutinitas rekursif, Anda mungkin mendapati bahwa hierarki tampilan Anda dirender sangat lambat. (Saya mempelajarinya dengan cara yang sulit) Seperti yang disebutkan dalam jawaban yang sangat baik, 'setNeedsLayout` lebih efisien dan akan membuat bingkai tersedia pada tata letak berikutnya, yang idealnya terjadi dalam waktu sekitar 1/60 detik.initWithCoder
?Saya memiliki masalah serupa di mana saya perlu menambahkan batas atas dan bawah ke
UITableView
yang mengubah ukuran berdasarkan pengaturan batasannya diUIStoryboard
. Saya dapat mengakses batasan yang diperbarui dengan- (void)viewDidLayoutSubviews
. Ini berguna agar Anda tidak perlu membuat subkelas tampilan dan mengganti metode tata letaknya.Tanpa memanggil metode dari
viewDidLayoutSubview
metode tersebut, hanya batas atas yang digambar dengan benar, karena batas bawah berada di luar layar.sumber
[super viewDidLayoutSubviews];
Bagi mereka yang mungkin masih menghadapi masalah seperti itu, terutama dengan TableviewCell.
Ganti saja metode ini:
Jika UITableViewCell atau UICollectionViewCell buat subkelas sel dan ganti metode yang sama:
sumber
Gunakan
-(void)viewWillAppear:(BOOL)animated
dan panggil[self.view layoutIfNeeded];
- Berhasil saya telah mencoba.karena jika Anda menggunakannya
-(void)viewDidLayoutSubviews
pasti akan berhasil tetapi metode ini dipanggil setiap kali UI Anda menuntut pembaruan / perubahan. Yang akan sulit dikelola. Tombol lunak adalah Anda menggunakan variabel bool untuk menghindari loop panggilan seperti itu. penggunaan yang lebih baikviewWillAppear
. IngatviewWillAppear
juga akan dipanggil jika view dimuat kembali (tanpa realokasi).sumber
Bingkai masih berlaku. Pada akhirnya, tampilan menggunakan properti bingkai untuk menata dirinya sendiri. Ini menghitung bingkai itu berdasarkan semua kendala. Batasan hanya digunakan untuk tata letak awal (dan kapan saja layoutSubviews dipanggil pada tampilan seperti setelah rotasi). Setelah itu, info posisi ada di properti frame. Atau apakah Anda melihat sebaliknya?
sumber