Secara vertikal UICollectionView
,
Apakah mungkin untuk memiliki sel lebar penuh , tetapi, biarkan tinggi dinamis dikontrol oleh tata letak otomatis ?
Ini menurut saya mungkin sebagai "pertanyaan paling penting di iOS tanpa jawaban yang benar-benar bagus".
Penting:
Perhatikan bahwa dalam 99% kasus, untuk mencapai lebar penuh sel + tinggi dinamis tata letak otomatis, cukup gunakan tampilan tabel. Semudah itu.
Jadi, apa contoh di mana Anda membutuhkan tampilan koleksi?
Tampilan koleksi jauh lebih kuat daripada tampilan tabel.
Satu contoh langsung di mana Anda benar - benar harus menggunakan tampilan koleksi, untuk mencapai sel lebar penuh + tinggi dinamis tata letak otomatis:
Jika Anda menganimasikan antara dua tata letak dalam tampilan koleksi. Misalnya, antara tata letak kolom 1 dan 2, saat perangkat berputar.
Itu idiom umum dan normal di iOS. Sayangnya itu hanya dapat dicapai dengan menyelesaikan masalah yang diajukan dalam QA ini. : - /
sumber
SpringDamping
daninitialSpringVelocity
) di tabel Cell ..... lihat Daftar Bouncy ini menggunakan tableView ,,,, pastebin.com/pFRQhkrX Anda dapat menganimasikanTableViewCell
tabel dalamwillDisplayCell:(UITableViewCell *)cell
metode delgate @Fattie yang dapat Anda terima jawaban yang memecahkan masalah Anda untuk membantu orang lain yang mencari masalah yang samaJawaban:
1. Solusi untuk iOS 13+
Dengan Swift 5.1 dan iOS 13, Anda dapat menggunakan objek Tata Letak Komposisi untuk memecahkan masalah Anda.
Kode contoh lengkap berikut menunjukkan cara menampilkan multiline
UILabel
di dalam lebar penuhUICollectionViewCell
:CollectionViewController.swift
HeaderView.swift
CustomCell.swift
Tampilan yang diharapkan:
2. Solusi untuk iOS 11+
Dengan Swift 5.1 dan iOS 11, Anda dapat membuat subkelas
UICollectionViewFlowLayout
dan menyetelestimatedItemSize
propertinya keUICollectionViewFlowLayout.automaticSize
(ini memberi tahu sistem bahwa Anda ingin menangani autoresisasiUICollectionViewCell
). Anda kemudian harus menggantilayoutAttributesForElements(in:)
danlayoutAttributesForItem(at:)
mengatur lebar sel. Terakhir, Anda harus menggantipreferredLayoutAttributesFitting(_:)
metode sel Anda dan menghitung tingginya.Kode lengkap berikut menunjukkan cara menampilkan multiline
UILabel
di dalam lebar penuhUIcollectionViewCell
(dibatasi olehUICollectionView
area aman danUICollectionViewFlowLayout
sisipan):CollectionViewController.swift
CustomFlowLayout.swift
HeaderView.swift
CustomCell.swift
Berikut beberapa implementasi alternatif untuk
preferredLayoutAttributesFitting(_:)
:Tampilan yang diharapkan:
sumber
Masalah
Anda mencari tinggi otomatis dan juga ingin memiliki lebar penuh, tidak mungkin untuk menggunakan keduanya
UICollectionViewFlowLayoutAutomaticSize
.Anda ingin menggunakan
UICollectionView
jadi di bawah ini adalah solusi untuk Anda.Larutan
1. Jika Anda memiliki hanya
UILabel
dalamCollectionViewCell
dari yang ditetapkannumberOfLines=0
dan yang menghitung ketinggian yang diharapkanUIlable
, lewati ketiga parameter2. Jika Anda
CollectionViewCell
hanya berisiUIImageView
dan jika itu seharusnya dinamis dalam Ketinggian daripada yang Anda butuhkan untuk mendapatkan ketinggianUIImage
(AndaUIImageView
harus memilikiAspectRatio
kendala)3. Jika mengandung keduanya maka hitung tinggi mereka dan jumlahkan keduanya.
1. Tambahkan
UICollectionViewDelegateFlowLayout
delegasi di viewController Anda2. Menerapkan metode delegasi
Saya harap ini akan membantu Anda.
sumber
return CGSize(width: view.frame.width/2, height: expectedHeight)
Juga pertahankan Padding dalam akun daripada mengembalikan lebar jika tidak dua sel tidak akan muat dalam satu baris.Ada beberapa cara untuk mengatasi masalah ini.
Salah satu caranya adalah Anda dapat memberi tata letak aliran tampilan koleksi perkiraan ukuran dan menghitung ukuran sel.
Catatan: Seperti yang disebutkan dalam komentar di bawah, mulai iOS 10 Anda tidak perlu lagi menyediakan dan memperkirakan ukuran untuk memicu panggilan ke sel
func preferredLayoutAttributesFitting(_ layoutAttributes:)
. Sebelumnya (iOS 9) akan meminta Anda untuk memberikan perkiraan ukuran jika Anda ingin meminta sel prefferedLayoutAttributes.(dengan asumsi Anda menggunakan papan cerita dan tampilan koleksi terhubung melalui IB)
Untuk sel sederhana itu biasanya sudah cukup. Jika ukurannya masih salah, dalam sel tampilan koleksi Anda dapat menggantifunc preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes
, yang akan memberi Anda kontrol butiran yang lebih halus atas ukuran sel. Catatan: Anda masih perlu memberikan perkiraan ukuran pada tata letak aliran .Kemudian ganti
func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes
untuk mengembalikan ukuran yang benar.Alternatifnya, sebagai gantinya Anda dapat menggunakan sel ukuran untuk menghitung ukuran sel di file
UICollectionViewDelegateFlowLayout
.Meskipun ini bukan contoh siap produksi yang sempurna, ini akan membantu Anda memulai dengan arah yang benar. Saya tidak bisa mengatakan ini adalah praktik terbaik, tetapi ini berfungsi untuk saya, bahkan dengan sel yang cukup kompleks yang berisi banyak label, yang mungkin atau mungkin tidak membungkus ke beberapa baris.
sumber
preferredLayoutAttributesFitting
. Saya kemudian menambahkan batasan saya sendiri dalam fungsi tersebut, mengikat dimensi tetap dari estimItemSize, FWIW, lihat jawaban saya di bawah.Saya menemukan solusi yang cukup mudah untuk masalah itu: Di dalam CollectionViewCell saya, saya mendapat UIView () yang sebenarnya hanya latar belakang. Untuk mendapatkan lebar penuh saya hanya mengatur Jangkar berikut
"Keajaiban" terjadi di baris pertama. Saya mengatur widthAnchor secara dinamis ke lebar layar. Yang juga penting adalah mengurangi insets CollectionView Anda. Jika tidak, sel tidak akan muncul. Jika Anda tidak ingin memiliki tampilan latar belakang seperti itu, buat saja tidak terlihat.
FlowLayout menggunakan pengaturan berikut
Hasilnya adalah sel berukuran lebar penuh dengan tinggi dinamis.
sumber
KERJA!!! Diuji di IOS: 12.1 Swift 4.1
Saya memiliki solusi yang sangat sederhana yang hanya berfungsi tanpa pemutusan kendala.
ViewControllerClass saya
Kelas CustomCell:
Bahan utama adalah systemLayoutSizeFitting fungsi dalam Customcell. Dan juga kita harus mengatur lebar tampilan di dalam Sel dengan batasan.
sumber
Anda harus menambahkan batasan lebar ke CollectionViewCell
sumber
Set
estimatedItemSize
tata letak aliran Anda:Tentukan batasan lebar dalam sel dan setel agar sama dengan lebar tampilan super:
Contoh lengkapnya
Diuji di iOS 11.
sumber
Secara pribadi saya menemukan cara terbaik untuk memiliki UICollectionView di mana AutoLayout menentukan ukuran sementara setiap Sel dapat memiliki ukuran yang berbeda adalah dengan mengimplementasikan fungsi UICollectionViewDelegateFlowLayout sizeForItemAtIndexPath saat menggunakan Cell yang sebenarnya untuk mengukur ukurannya.
Saya membicarakan hal ini di salah satu postingan blog saya
Semoga yang satu ini akan membantu Anda mencapai apa yang Anda inginkan. Saya tidak 100% yakin tetapi saya percaya tidak seperti UITableView di mana Anda benar-benar dapat memiliki ketinggian sel otomatis sepenuhnya dengan menggunakan AutoLayout yang tidak berhubungan dengan
UICollectionView tidak memiliki cara yang memungkinkan AutoLayout menentukan ukuran karena UICollectionViewCell tidak harus memenuhi seluruh lebar layar.
Tapi ini pertanyaan untuk Anda : Jika Anda membutuhkan sel lebar layar penuh, mengapa Anda repot-repot menggunakan UICollectionView daripada UITableView lama yang bagus yang dilengkapi dengan sel ukuran otomatis?
sumber
Menurut komentar saya atas jawaban Eric, solusi saya sangat mirip dengan miliknya, tetapi saya harus menambahkan batasan di preferSizeFor ... untuk membatasi ke dimensi tetap.
Pertanyaan ini memiliki sejumlah duplikat, saya menjawabnya secara mendetail di sini , dan memberikan contoh aplikasi yang berfungsi di sini.
sumber
Tidak yakin apakah ini memenuhi syarat sebagai "jawaban yang sangat bagus", tapi itulah yang saya gunakan untuk mencapai ini. Tata letak aliran saya horizontal, dan saya mencoba menyesuaikan lebar dengan tata letak otomatis, jadi ini mirip dengan situasi Anda.
Kemudian di pengontrol tampilan tempat batasan autolayout diubah, saya mengaktifkan NSNotification.
Di subkelas UICollectionView saya, saya mendengarkan pemberitahuan itu:
dan membatalkan tata letak:
Hal ini menyebabkan
sizeForItemAt
dipanggil lagi menggunakan ukuran baru tampilan koleksi. Dalam kasus Anda, ini harus dapat diperbarui dengan batasan baru yang tersedia di tata letak.sumber
Di Anda
viewDidLayoutSubviews
, setelestimatedItemSize
ke lebar penuh (tata letak mengacu pada objek UICollectionViewFlowLayout):Di sel Anda, pastikan bahwa batasan Anda menyentuh bagian atas dan bawah sel (kode berikut menggunakan Kartografi untuk menyederhanakan pengaturan batasan tetapi Anda dapat melakukannya dengan NSLayoutConstraint atau IB jika Anda mau):
Voila, sel-sel Anda sekarang akan tumbuh otomatis!
sumber
Tidak ada solusi yang berfungsi untuk saya karena saya membutuhkan lebar dinamis untuk menyesuaikan antara lebar iPhone.
sumber
Dari iOS 10, kami memiliki API baru tentang tata letak aliran untuk melakukannya.
Yang harus Anda lakukan adalah menyetel
flowLayout.estimatedItemSize
ke konstanta baruUICollectionViewFlowLayoutAutomaticSize
,.Sumber
sumber
AutoLayout dapat digunakan untuk mengubah ukuran sel secara otomatis di CollectionView dalam 2 langkah mudah:
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
collectionView(:cellForItemAt:)
untuk membatasi lebar contentView menjadi lebar collectionView.Itu saja Anda akan mendapatkan hasil yang diinginkan. Lihat inti berikut untuk kode lengkap:
Referensi / Kredit:
Tangkapan layar:
sumber
Anda harus mewarisi kelas UICollectionViewDelegateFlowLayout di collectionViewController Anda. Kemudian tambahkan fungsinya:
Menggunakan itu, Anda memiliki ukuran lebar dari lebar layar.
Dan sekarang Anda memiliki collectionViewController dengan baris sebagai tableViewController.
Jika Anda ingin ukuran tinggi setiap sel menjadi dinamis, mungkin Anda harus membuat sel khusus untuk setiap sel yang Anda butuhkan.
sumber