Saya memiliki UITableView
menjalankan di bawah iOS 8 dan saya menggunakan ketinggian sel otomatis dari kendala di storyboard.
Salah satu sel saya berisi satu UITextView
dan saya membutuhkannya untuk berkontraksi dan berkembang berdasarkan input pengguna - ketuk untuk mengecilkan / perluas teks.
Saya melakukan ini dengan menambahkan kendala runtime ke tampilan teks dan mengubah konstanta pada kendala sebagai respons terhadap peristiwa pengguna:
-(void)collapse:(BOOL)collapse; {
_collapsed = collapse;
if(collapse)
[_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
else
[_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];
[self setNeedsUpdateConstraints];
}
Setiap kali saya melakukan ini, saya membungkusnya dalam tableView
pembaruan dan menelepon [tableView setNeedsUpdateConstraints]
:
[tableView beginUpdates];
[_briefCell collapse:!_showFullBriefText];
[tableView setNeedsUpdateConstraints];
// I have also tried
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.
[tableView endUpdates];
Ketika saya melakukan ini, sel saya berkembang (dan menjiwai saat melakukannya) tapi saya mendapat peringatan kendala:
2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",
"<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-| (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",
"<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'] (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",
"<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>
388 adalah tinggi saya yang dihitung, kendala lain pada UITextView
adalah milik saya dari Xcode / IB.
Yang terakhir mengganggu saya - saya menduga itu UIView-Encapsulated-Layout-Height
adalah tinggi sel yang dihitung saat pertama kali diberikan - (saya menetapkan UITextView
tinggi badan saya menjadi> = 70,0) namun sepertinya tidak benar bahwa batasan turunan ini kemudian mengesampingkan suatu pembaruan cnstraint pengguna.
Lebih buruk lagi, meskipun kode tata letak mengatakan itu mencoba untuk memecahkan batasan ketinggian saya, itu tidak - ia melanjutkan untuk menghitung ulang tinggi sel dan semuanya menarik seperti yang saya inginkan.
Jadi, apa itu NSLayoutConstraint
UIView-Encapsulated-Layout-Height
(saya menduga itu adalah tinggi yang dihitung untuk ukuran sel otomatis) dan bagaimana saya harus memaksanya untuk menghitung ulang secara bersih?
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
. Saya pikir bahwa pengaturan awal topeng autoresize menghentikan kendala terakhir yang ditambahkan. Saya menemukan solusi ini di sini: github.com/wordpress-mobile/WordPress-iOS/commit/…<rect key="frame" x="0.0" y="0.0" width="600" height="110"/>
dengan definisi, membuat saya percaya bahwa ini adalah bug IB . Setidaknya milikku toh.Jawaban:
Cobalah untuk menurunkan prioritas Anda
_collapsedtextHeightConstraint
ke 999. Dengan cara ituUIView-Encapsulated-Layout-Height
kendala yang disediakan sistem selalu diutamakan.Ini didasarkan pada apa yang Anda kembali
-tableView:heightForRowAtIndexPath:
. Pastikan untuk mengembalikan nilai yang tepat dan kendala Anda sendiri dan yang dihasilkan harus sama. Prioritas yang lebih rendah untuk kendala Anda sendiri hanya diperlukan sementara untuk mencegah konflik saat animasi runtuh / luas sedang terbang.sumber
UIView-Encapsulated-Layout-Height
kendala ditambahkan oleh UITableView setelah ketinggian ditentukan. Saya menghitung ketinggian berdasarkan padasystemLayoutSizeFittingSize
contentView. Di sini,UIView-Encapsulated-Layout-Height
tidak masalah. Kemudian, tableView menetapkan contentSize secara eksplisit ke nilai yang dikembalikan olehheightForRowAtIndexPath:
. Dalam hal ini benar untuk menurunkan prioritas kendala khusus kami karena kendala tableView harus diutamakan setelah rowHeights dihitung.UIView-Encapsulated-Layout-Height
salah jika saya tidak menurunkan prioritas ...UIView-Encapsulated-Layout-Width
dalam kasus saya hanya salah, tetapi tampaknya lebih disukai daripada kendala eksplisit saya saat runtime.Saya memiliki skenario yang sama: tampilan tabel dengan satu sel baris, di mana ada beberapa baris objek UILabel. Saya menggunakan iOS 8 dan autolayout.
Ketika saya diputar saya mendapat sistem salah menghitung tinggi baris (43,5 jauh lebih sedikit dari tinggi sebenarnya). Sepertinya:
Itu bukan hanya peringatan. Tata letak sel tampilan tabel saya mengerikan - semua teks tumpang tindih pada satu baris teks.
Itu mengejutkan saya bahwa baris berikut "memperbaiki" masalah saya secara ajaib (autolayout tidak mengeluh apa pun dan saya mendapatkan apa yang saya harapkan di layar):
dengan atau tanpa baris ini:
sumber
estimatedRowHeight
semakin seringcellForRowAtIndexPath
akan dipanggil pada awalnya. tinggi tampilan tabel dibagi dengan taksiran kaliRowHeight, tepatnya. Pada iPad Pro 12 inci, ini berpotensi menjadi angka dalam ribuan dan akan memalu sumber data dan dapat menyebabkan penundaan yang signifikan.Saya bisa mendapatkan peringatan untuk pergi dengan menetapkan prioritas pada salah satu nilai dalam kendala yang menurut pesan peringatan harus dipatahkan (di bawah
"Will attempt to recover by breaking constraint"
). Tampaknya selama saya menetapkan prioritas untuk sesuatu yang lebih besar dari itu49
, peringatan itu hilang.Bagi saya ini berarti mengubah batasan saya, peringatan mengatakan itu berusaha untuk mematahkan:
@"V:|[contentLabel]-[quoteeLabel]|"
untuk:
@"V:|-0@500-[contentLabel]-[quoteeLabel]|"
Bahkan, saya dapat menambahkan prioritas ke salah satu elemen dari kendala itu dan itu akan berhasil. Tampaknya tidak masalah yang mana. Sel saya berakhir dengan ketinggian yang tepat dan peringatan tidak ditampilkan. Roger, misalnya, coba tambahkan
@500
tepat setelah388
batasan nilai tinggi (mis388@500
.).Saya tidak sepenuhnya yakin mengapa ini berhasil, tetapi saya telah melakukan sedikit penyelidikan. Di enum NSLayoutPriority , tampaknya
NSLayoutPriorityFittingSizeCompression
tingkat prioritasnya adalah50
. Dokumentasi untuk tingkat prioritas mengatakan:Itu dokumentasi untuk direferensikan
fittingSize
pesan berbunyi:Saya belum menggali lebih dari itu tetapi tampaknya masuk akal bahwa ini ada hubungannya dengan di mana masalahnya.
sumber
99,9% dari waktu, saat menggunakan sel atau header khusus, semua konflik
UITableViews
terjadi ketika tabel memuat pertama kali. Setelah dimuat Anda biasanya tidak akan melihat konflik lagi.Ini terjadi karena sebagian besar pengembang biasanya menggunakan ketinggian tetap atau batasan jangkar dari beberapa jenis untuk tata letak elemen di sel / header. Konflik terjadi karena ketika
UITableView
beban pertama / diletakkan, ia mengatur ketinggian selnya menjadi 0. Ini jelas bertentangan dengan kendala Anda sendiri. Untuk mengatasi ini, cukup setel batasan ketinggian tetap apa pun ke prioritas yang lebih rendah (.defaultHigh
). Baca dengan hati-hati pesan konsol dan lihat kendala apa yang diputus sistem tata letak. Biasanya ini yang perlu diubah prioritasnya. Anda dapat mengubah prioritas seperti ini:sumber
Saya bisa mengatasi kesalahan ini dengan menghapus palsu
cell.layoutIfNeeded()
bahwa aku telah di sayatableView
'scellForRowAt
metode.sumber
Alih-alih menginformasikan tampilan tabel untuk memperbarui batasannya, coba muat ulang sel:
UIView-Encapsulated-Layout-Height
mungkin tinggi tampilan tabel dihitung untuk sel selama beban awal, berdasarkan kendala sel pada waktu itu.sumber
Kemungkinan lain:
Jika Anda menggunakan tata letak otomatis untuk menghitung tinggi sel (tinggi contentView, sebagian besar waktu seperti di bawah ini), dan jika Anda memiliki pemisah uitableview, Anda perlu menambahkan tinggi pemisah, untuk mengembalikan tinggi sel. Setelah Anda mendapatkan ketinggian yang benar, Anda tidak akan memiliki peringatan pembayaran otomatis itu.
sumber
UITableViewAutomaticDimension
diheightForRowAtIndexPath
saya kembali[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] + 0.1
[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 0.1
Seperti yang disebutkan oleh Jesse dalam komentar pertanyaan, ini bekerja untuk saya:
FYI, masalah ini tidak terjadi di iOS 10.
sumber
Saya mengalami kesalahan ini saat menggunakan UITableViewAutomaticDimension dan mengubah batasan ketinggian pada tampilan di dalam sel.
Saya akhirnya menemukan bahwa itu karena nilai konstan kendala tidak dibulatkan ke bilangan bulat terdekat.
sumber
Mengubah ukuran tampilan teks agar sesuai dengan isinya, dan memperbarui batasan ketinggian konstan ke ketinggian yang dihasilkan, memperbaiki
UIView-Encapsulated-Layout-Height
konflik kendala bagi saya, misalnya:sumber
Setelah menghabiskan beberapa jam menggaruk-garuk kepala saya dengan bug ini, saya akhirnya menemukan solusi yang bekerja untuk saya. masalah utama saya adalah bahwa saya memiliki beberapa nib yang terdaftar untuk jenis sel yang berbeda tetapi satu jenis sel secara khusus diizinkan untuk memiliki ukuran yang berbeda (tidak semua contoh sel itu akan memiliki ukuran yang sama). jadi masalah muncul ketika tampilan tabel mencoba untuk mengeluarkan sel dari jenis itu dan kebetulan memiliki ketinggian yang berbeda. Saya menyelesaikannya dengan mengatur
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; self.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});
setiap kali sel memiliki data untuk menghitung ukurannya. Saya pikir itu bisa masuk
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
sesuatu seperti
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; cell.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});
Semoga ini membantu!
sumber
TableView mendapatkan tinggi untuk sel di indexPath dari delegasi. lalu dapatkan sel dari
cellForRowAtIndexPath
:jika cell.contentView.height: 0 // <-> (UIView-Encapsulated-Layout-Height: 0 @ 1000) top (10 @ 1000) bentrok dengan (UIView-Encapsulated-Layout-Height: 0 @ 1000),
karena mereka prioritas sama dengan 1000. Kita perlu menetapkan prioritas utama di bawah
UIView-Encapsulated-Layout-Height
prioritas.sumber
Saya mendapat pesan seperti ini:
Saya menggunakan custom
UITableViewCell
denganUITableViewAutomaticDimension
untuk ketinggian. Dan saya juga menerapkanestimatedHeightForRowAtIndex:
metode ini.Kendala yang memberi saya masalah tampak seperti ini
Mengubah batasan untuk ini akan memperbaiki masalah, tetapi seperti jawaban lain saya merasa bahwa ini tidak benar, karena menurunkan prioritas kendala yang saya inginkan:
Namun, yang saya perhatikan adalah bahwa jika saya benar-benar hanya menghapus prioritas, ini juga berfungsi dan saya tidak mendapatkan log kendala pemecah:
Ini adalah sedikit misteri tentang apa perbedaan antara
|-6-[title]-6-|
dan|-[title-|
. Tetapi menentukan ukuran bukan masalah bagi saya dan menghilangkan log, dan saya tidak perlu menurunkan prioritas kendala yang diperlukan.sumber
Setel ini
view.translatesAutoresizingMaskIntoConstraints = NO;
harus menyelesaikan masalah ini.sumber
Saya punya masalah serupa dengan sel tampilan koleksi.
Saya menyelesaikannya dengan menurunkan prioritas batasan akhir yang dikaitkan dengan bagian bawah sel (yang terakhir dalam rantai dari atas ke bawah tampilan - inilah yang akhirnya menentukan tingginya) menjadi 999.
Ketinggian sel itu benar, dan peringatan itu hilang.
sumber