Saya memiliki UITableView
dengan kustom yang UITableViewCell
ditentukan di storyboard menggunakan tata letak otomatis. Sel memiliki beberapa multiline UILabels
.
The UITableView
muncul ke ketinggian sel benar menghitung, tapi untuk beberapa sel pertama yang tinggi tidak benar dibagi antara label. Setelah menggulir sedikit, semuanya berfungsi seperti yang diharapkan (bahkan sel yang awalnya salah).
- (void)viewDidLoad {
[super viewDidLoad]
// ...
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
// ...
// Set label.text for variable length string.
return cell;
}
Apakah ada sesuatu yang mungkin saya lewatkan, yang menyebabkan tata letak otomatis tidak dapat melakukan tugasnya beberapa kali pertama?
Saya telah membuat proyek contoh yang menunjukkan perilaku ini.
ios
uitableview
ios8
autolayout
ios-autolayout
blackp
sumber
sumber
Jawaban:
Saya tidak tahu ini didokumentasikan dengan jelas atau tidak, tetapi menambahkan
[cell layoutIfNeeded]
sebelum mengembalikan sel memecahkan masalah Anda.sumber
-layoutIfNeeded
dalam sel-awakeFromNib
. Saya lebih suka meneleponlayoutIfNeeded
jika saya tahu mengapa itu perlu.Ini berhasil untuk saya ketika solusi serupa lainnya tidak:
Ini sepertinya bug yang sebenarnya karena saya sangat akrab dengan AutoLayout dan cara menggunakan UITableViewAutomaticDimension, namun saya kadang-kadang masih menemukan masalah ini. Saya senang akhirnya menemukan sesuatu yang berfungsi sebagai solusi.
sumber
super.didMoveToSuperview()
didMoveToSuperview
: "Implementasi default metode ini tidak melakukan apa-apa."Menambahkan
[cell layoutIfNeeded]
dicellForRowAtIndexPath
tidak bekerja untuk sel-sel yang awalnya menggulir out-of-view.Juga tidak mengawali dengan
[cell setNeedsLayout]
.Anda masih harus menggulir sel tertentu keluar dan kembali ke tampilan agar ukurannya benar.
Ini cukup membuat frustrasi karena sebagian besar pengembang memiliki Jenis Dinamis, Tata Letak Otomatis, dan Sel Ukuran Mandiri yang berfungsi dengan baik - kecuali untuk kasus yang mengganggu ini. Bug ini memengaruhi semua pengontrol tampilan tabel saya yang "lebih tinggi".
sumber
[cell layoutSubviews]
alih-alih layoutIfNeeded mungkin bisa diperbaiki. Lihat stackoverflow.com/a/33515872/1474113Saya memiliki pengalaman yang sama di salah satu proyek saya.
Mengapa ini terjadi?
Sel dirancang di Storyboard dengan beberapa lebar untuk beberapa perangkat. Misalnya 400px. Misalnya label Anda memiliki lebar yang sama. Saat dimuat dari storyboard, ia memiliki lebar 400px.
Inilah masalahnya:
tableView:heightForRowAtIndexPath:
dipanggil sebelum tata letak sel itu subview.Maka dihitung tinggi label dan sel dengan lebar 400px. Tapi Anda berjalan di perangkat dengan layar, misalnya, 320px. Dan ketinggian yang dihitung secara otomatis ini salah. Hanya karena sel
layoutSubviews
terjadi hanya setelahtableView:heightForRowAtIndexPath:
Bahkan jika Anda mengaturpreferredMaxLayoutWidth
label Anda secara manual dilayoutSubviews
dalamnya tidak membantu.Solusi saya:
1) Subclass
UITableView
dan overridedequeueReusableCellWithIdentifier:forIndexPath:
. Atur lebar sel sama dengan lebar tabel dan paksa tata letak sel.2) Subkelas
UITableViewCell
. SetelpreferredMaxLayoutWidth
secara manual untuk label Anda dilayoutSubviews
. Anda juga memerlukan tata letak secara manualcontentView
, karena tata letak tidak otomatis setelah bingkai sel berubah (saya tidak tahu mengapa, tetapi memang demikian)sumber
cell.frame.size.width = tableview.frame.width
kemudiancell.layoutIfNeeded()
dalamcellForRowAt
fungsi melakukan trik untuk sayaSaya memiliki masalah serupa, pada pemuatan pertama, tinggi baris tidak dihitung tetapi setelah beberapa menggulir atau pergi ke layar lain dan saya kembali ke baris layar ini dihitung. Pada pemuatan pertama barang saya dimuat dari internet dan pada pemuatan kedua barang saya dimuat pertama dari Data Inti dan dimuat ulang dari internet dan saya perhatikan bahwa tinggi baris dihitung saat memuat ulang dari internet. Jadi saya perhatikan bahwa ketika tableView.reloadData () dipanggil selama animasi segue (masalah yang sama dengan push dan present segue), tinggi baris tidak dihitung. Jadi saya menyembunyikan tampilan tabel pada inisialisasi tampilan dan meletakkan pemuat aktivitas untuk mencegah efek buruk bagi pengguna dan saya memanggil tableView.reloadData setelah 300ms dan sekarang masalahnya telah terpecahkan. Saya pikir ini adalah bug UIKit tetapi solusi ini berhasil.
Saya meletakkan baris ini (Swift 3.0) di penangan penyelesaian pemuatan item saya
Ini menjelaskan mengapa bagi sebagian orang, meletakkan reloadData di layoutSubviews untuk menyelesaikan masalah
sumber
tidak ada solusi di atas yang berhasil untuk saya, yang berhasil adalah resep ajaib ini: panggil mereka dalam urutan ini:
tableView.reloadData()
tableView.layoutIfNeeded() tableView.beginUpdates() tableView.endUpdates()
data tableView saya diisi dari layanan web, dalam panggilan kembali koneksi saya menulis baris di atas.
sumber
Dalam kasus saya, baris terakhir UILabel terpotong saat sel ditampilkan untuk pertama kalinya. Itu terjadi secara acak dan satu-satunya cara untuk mengukurnya dengan benar adalah dengan menggulir sel keluar dari tampilan dan membawanya kembali. Saya mencoba semua solusi yang mungkin ditampilkan sejauh ini (layoutIfNeeded..reloadData) tetapi tidak ada yang berhasil untuk saya. Triknya adalah dengan mengatur "Autoshrink" ke Skala Font Minimuum (0,5 untuk saya). Cobalah
sumber
Tambahkan batasan untuk semua konten dalam sel khusus tampilan tabel, lalu perkirakan tinggi baris tampilan tabel dan setel tinggi baris ke dimensi otomatis dengan dalam pemuatan viewdid:
Untuk memperbaiki masalah pemuatan awal tersebut, terapkan metode layoutIfNeeded dengan dalam sel tampilan tabel kustom:
sumber
estimatedRowHeight
ke nilai> 0 dan bukanUITableViewAutomaticDimension
(yaitu -1), jika tidak, tinggi baris otomatis tidak akan berfungsi.Saya telah mencoba sebagian besar jawaban atas pertanyaan ini dan tidak bisa mendapatkan satu pun dari mereka untuk bekerja. Satu-satunya solusi fungsional yang saya temukan adalah menambahkan yang berikut ini ke
UITableViewController
subkelas saya :The
UIView.performWithoutAnimation
panggilan diperlukan, jika tidak, anda akan melihat normal tampilan tabel animasi sebagai beban controller tampilan.sumber
viewWillAppear
tidak berhasil untuk saya, tetapi melakukannya di dalamviewDidAppear
berhasil.Pengaturan
preferredMaxLayoutWidth
membantu dalam kasus saya. saya tambahkandalam kode saya.
Juga mengacu pada Teks baris tunggal mengambil dua baris di UILabel dan http://openradar.appspot.com/17799811 .
sumber
menelepon ke
cell.layoutIfNeeded()
dalamcellForRowAt
berfungsi untuk saya di iOS 10 dan iOS 11, tetapi tidak di iOS 9.untuk mendapatkan pekerjaan ini di ios 9 juga, saya menelepon
cell.layoutSubviews()
dan berhasil.sumber
Bagi saya tidak ada pendekatan ini yang berhasil, tetapi saya menemukan bahwa label tersebut memiliki
Preferred Width
set eksplisit di Interface Builder. Menghapus itu (menghapus centang "Eksplisit") dan kemudian menggunakanUITableViewAutomaticDimension
berfungsi seperti yang diharapkan.sumber
Saya mencoba semua solusi di halaman ini tetapi menghapus centang kelas ukuran penggunaan kemudian memeriksanya lagi memecahkan masalah saya.
Sunting: Menghapus centang kelas ukuran menyebabkan banyak masalah di papan cerita jadi saya mencoba solusi lain. Saya mengisi tampilan tabel saya di pengontrol tampilan
viewDidLoad
danviewWillAppear
metode saya. Ini memecahkan masalah saya.sumber
Saya memiliki masalah dengan mengubah ukuran label, jadi saya hanya perlu melakukan
chatTextLabel.text = chatMessage.message chatTextLabel? .UpdateConstraints () setelah menyiapkan teks
// kode lengkap
sumber
Dalam kasus saya, saya memperbarui di siklus lain. Jadi tinggi tableViewCell diperbarui setelah labelText disetel. Saya menghapus blok asinkron.
sumber
Pastikan Anda tidak menyetel teks label dalam metode delegasi 'willdisplaycell' pada tampilan tabel. Setel teks label dalam metode delegasi 'cellForRowAtindexPath' untuk penghitungan ketinggian dinamis.
Sama-sama :)
sumber
Dalam kasus saya, tampilan tumpukan di dalam sel menyebabkan masalah. Sepertinya itu bug. Setelah saya menghapusnya, masalahnya teratasi.
sumber
Masalahnya adalah bahwa sel awal dimuat sebelum kita memiliki tinggi baris yang valid. Solusinya adalah memaksa tabel memuat ulang saat tampilan muncul.
sumber
Hanya untuk iOS 12+, 2019 dan seterusnya ...
Contoh berkelanjutan dari ketidakmampuan Apple yang aneh, di mana masalah terus berlanjut selama bertahun-tahun.
Tampaknya memang demikian
akan memperbaikinya. (Anda kehilangan beberapa kinerja tentu saja.)
Begitulah hidup dengan Apple.
sumber
Dalam kasus saya, masalah ketinggian sel terjadi setelah tampilan tabel awal dimuat, dan tindakan pengguna terjadi (mengetuk tombol di sel yang memiliki efek mengubah tinggi sel). Saya tidak dapat membuat sel mengubah tingginya kecuali saya melakukannya:
Saya sudah mencoba
tapi itu tidak berhasil.
sumber
Di Swift 3. Saya harus memanggil self.layoutIfNeeded () setiap kali saya memperbarui teks sel yang dapat digunakan kembali.
sumber
Tak satu pun dari solusi di atas berhasil tetapi kombinasi saran berikut berhasil.
Harus menambahkan yang berikut ini di viewDidLoad ().
Kombinasi reloadData, setNeedsLayout, dan layoutIfNeeded di atas berfungsi, tetapi tidak yang lain. Bisa jadi khusus untuk sel dalam proyek sekalipun. Dan ya, harus memanggil reloadData dua kali untuk membuatnya berfungsi.
Setel juga berikut ini di viewDidLoad
Di tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
sumber
reloadData/beginUpdates/endUpdates/reloadData
juga bekerja;reloadData
harus dipanggil untuk kedua kalinya. Tidak perlu membungkusnyaasync
.Saya mengalami masalah ini dan memperbaikinya dengan memindahkan kode inisialisasi tampilan / label saya DARI
tableView(willDisplay cell:)
KEtableView(cellForRowAt:)
.sumber
willDisplay
akan memiliki kinerja yang lebih baik daripadacellForRowAt
. Gunakan yang terbaru hanya untuk membuat sel yang tepat.willDisplay
memiliki performa yang lebih baik, iS merekomendasikan untuk menginisialisasi UI sel AndacellForRowAt
saat tata letaknya otomatis. Memang, tata letak dihitung oleh UIKit setelah cellForRowAt et sebelum willDisplay. Jadi jika tinggi sel Anda bergantung pada isinya, inisialisasi konten label (atau apa pun) dicellForRowAt
.gunakan metode di atas yang mengembalikan ketinggian baris secara dinamis. Dan tetapkan tinggi dinamis yang sama ke label yang Anda gunakan.
Kode ini membantu Anda menemukan ketinggian dinamis untuk teks yang ditampilkan di label.
sumber