UICollectionView di dalam UITableViewCell - tinggi dinamis?

125

Salah satu layar aplikasi kami mengharuskan kami untuk menempatkan bagian UICollectionViewdalam file UITableViewCell. Ini UICollectionViewakan memiliki jumlah item yang dinamis, menghasilkan ketinggian yang juga harus dihitung secara dinamis. Namun, saya mengalami masalah saat mencoba menghitung ketinggian tertanam UICollectionView.

Keseluruhan kami UIViewControllerdibuat di Storyboards dan menggunakan tata letak otomatis. Tapi, saya tidak tahu bagaimana cara menaikkan ketinggian secara dinamis UITableViewCellberdasarkan ketinggian UICollectionView.

Adakah yang bisa memberikan beberapa tip atau saran tentang bagaimana mencapai ini?

Manusia bayangan
sumber
dapatkah Anda menceritakan lebih banyak tentang tata letak yang ingin Anda capai? Apakah ketinggian UITableViewCellberbeda dari tampilan tabel acutal-nya? Apakah Anda memerlukan pengguliran vertikal pada UICollectionViewdanUITableView
apouche
3
Ketinggian UITableViewCell seharusnya dinamis, berdasarkan ketinggian UICollectionView yang merupakan bagian dari sel tampilan tabel. Tata letak UICollectionView saya adalah 4 kolom dan jumlah baris yang dinamis. Jadi, dengan 100 item, saya akan memiliki 4 kolom dan 25 baris di UICollectionView saya. Tinggi sel tertentu - seperti yang ditunjukkan oleh heightForRowAtIndexPath UITableView - harus bisa disesuaikan berdasarkan ukuran UICollectionView tersebut. Apakah itu sedikit lebih jelas?
Shadowman
@Shadowman, tolong sarankan saya solusi untuk situasi ini
Ravi Ojha

Jawaban:

127

Jawaban yang benar adalah YA , Anda BISA melakukan ini.

Saya menemukan masalah ini beberapa minggu lalu. Ini sebenarnya lebih mudah dari yang Anda kira. Letakkan sel Anda di NIB (atau storyboard) dan sematkan agar tata letak otomatis melakukan semua pekerjaan

Diberikan struktur berikut:

TableView

TableViewCell

CollectionView

CollectionViewCell

CollectionViewCell

CollectionViewCell

[... jumlah sel variabel atau ukuran sel berbeda]

Solusinya adalah memberi tahu tata letak otomatis untuk menghitung ukuran collectionViewCell terlebih dahulu, lalu tampilan koleksi contentSize, dan menggunakannya sebagai ukuran sel Anda. Ini adalah metode UIView yang "melakukan keajaiban":

-(void)systemLayoutSizeFittingSize:(CGSize)targetSize 
     withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority 
           verticalFittingPriority:(UILayoutPriority)verticalFittingPriority

Anda harus menyetel di sini ukuran TableViewCell, yang dalam kasus Anda adalah contentSize CollectionView.

CollectionViewCell

Pada CollectionViewCell Anda harus memberi tahu sel ke tata letak setiap kali Anda mengubah model (misalnya: Anda menyetel UILabel dengan teks, maka sel tersebut harus di tata letak lagi).

- (void)bindWithModel:(id)model {
    // Do whatever you may need to bind with your data and 
    // tell the collection view cell's contentView to resize
    [self.contentView setNeedsLayout];
}
// Other stuff here...

TableViewCell

The TableViewCell melakukan keajaiban. Ini memiliki outlet untuk CollectionView Anda, memungkinkan tata letak otomatis untuk sel CollectionView menggunakan estimatedItemSize dari UICollectionViewFlowLayout .

Kemudian, triknya adalah menyetel ukuran sel tableView Anda pada metode systemLayoutSizeFittingSize .... (CATATAN: iOS8 atau lebih baru)

CATATAN: Saya mencoba menggunakan metode ketinggian sel delegasi dari tableView. -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPathTetapi sudah terlambat bagi sistem tata letak otomatis untuk menghitung CollectionView contentSize dan terkadang Anda mungkin menemukan sel yang diubah ukurannya salah.

@implementation TableCell

- (void)awakeFromNib {
    [super awakeFromNib];
    UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;

    // Configure the collectionView
    flow.minimumInteritemSpacing = ...;

    // This enables the magic of auto layout. 
    // Setting estimatedItemSize different to CGSizeZero 
    // on flow Layout enables auto layout for collectionView cells.
    // https://developer.apple.com/videos/play/wwdc2014-226/
    flow.estimatedItemSize = CGSizeMake(1, 1);

    // Disable the scroll on your collection view
    // to avoid running into multiple scroll issues.
    [self.collectionView setScrollEnabled:NO];
}

- (void)bindWithModel:(id)model {
    // Do your stuff here to configure the tableViewCell
    // Tell the cell to redraw its contentView        
    [self.contentView layoutIfNeeded];
}

// THIS IS THE MOST IMPORTANT METHOD
//
// This method tells the auto layout
// You cannot calculate the collectionView content size in any other place, 
// because you run into race condition issues.
// NOTE: Works for iOS 8 or later
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority {

    // With autolayout enabled on collection view's cells we need to force a collection view relayout with the shown size (width)
    self.collectionView.frame = CGRectMake(0, 0, targetSize.width, MAXFLOAT);
    [self.collectionView layoutIfNeeded];

    // If the cell's size has to be exactly the content 
    // Size of the collection View, just return the
    // collectionViewLayout's collectionViewContentSize.

    return [self.collectionView.collectionViewLayout collectionViewContentSize];
}

// Other stuff here...

@end

TableViewController

Ingatlah untuk mengaktifkan sistem tata letak otomatis untuk sel tableView di TableViewController Anda :

- (void)viewDidLoad {
    [super viewDidLoad];

    // Enable automatic row auto layout calculations        
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    // Set the estimatedRowHeight to a non-0 value to enable auto layout.
    self.tableView.estimatedRowHeight = 10;

}

KREDIT: @rbarbera membantu menyelesaikan masalah ini

Pablo Romeu
sumber
4
Ya. Ini bekerja. Ini harus menjadi jawaban yang diterima.
csotiriou
1
Dapatkah badan mana pun memberi saya kode contoh untuk itu? saya ingin menampilkan beberapa gambar dalam tampilan koleksi vertikal, yang ada di dalam sel tampilan tabel ..
Ravi Ojha
4
Akhirnya ini berhasil untuk saya, tetapi saya harus melakukan trik lain: cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);Ini akan "mensimulasikan" sel panjang dengan collectionView yang panjang, sehingga collectionView akan menghitung ukuran semua selnya. Jika tidak, collectionView hanya menghitung ukuran sel yang terlihat, dan salah menyetel tinggi talbeViewCell.
ingaham
20
ketika mengatur tinggi bingkai ke maksimum systemLayoutSizeFittingSize, saya mengalami masalah dengan cepat saat memuat ulang sel, aplikasi tampaknya macet setelah self.collectionView.layoutIfNeeded(). Saya memperbaikinya dengan mengatur tinggi bingkai dengan 1 daripada tinggi maksimum. Semoga membantu jika ada yang tersandung dalam masalah ini.
titan
6
Inilah yang memperbaikinya untuk saya - dalam systemLayoutSizeFitting, membalik urutan dari apa yang ditunjukkan dalam jawaban saat ini, jadi yang pertama collectionView.layoutIfNeeded()berjalan, lalucollectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
xaphod
101

Saya pikir solusi saya jauh lebih sederhana daripada yang diusulkan oleh @PabloRomeu.

Langkah 1. Buat outlet dari UICollectionViewke UITableViewCell subclass, di mana UICollectionViewditempatkan. Biarkan, namanya akancollectionView

Langkah 2. Tambahkan IB untuk UICollectionViewbatasan ketinggian dan buat jalan keluar UITableViewCell subclassjuga. Biarkan, namanya akan collectionViewHeight.

Langkah 3. tableView:cellForRowAtIndexPath:Tambahkan kode:

// deque a cell
cell.frame = tableView.bounds;
[cell layoutIfNeeded];
[cell.collectionView reloadData];
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height;
Igor
sumber
1
Apakah Anda benar-benar mencoba ini? Tampaknya tidak mungkin untuk menyetel batasan ketinggian pada tampilan koleksi dan menyematkannya ke margin sel tampilan tabel. Anda berakhir dengan terlalu sedikit batasan (karena itu peringatan ukuran nol), atau Anda berakhir dengan batasan yang bertentangan (salah satunya diabaikan). Tolong jelaskan bagaimana mengatur batasan untuk solusi ini.
Dale
2
Saya sudah berhasil. Saya menambahkan batasan untuk collectionViewsemua sisi UITableViewCelldan set tableView.estimatedRowHeight = 44;dantableView.rowHeight = UITableViewAutomaticDimension;
Igor
3
Yang ini bekerja seperti juara ... sederhana dan efisien ... terima kasih. Jika untuk seseorang itu tidak berfungsi maka mungkin alasannya, kita perlu mengikat bagian bawah tampilan koleksi ke bagian bawah sel tampilan tabel. Kemudian itu akan mulai bekerja. Selamat coding .. :)
Sebin Roy
2
Apakah ini akan berfungsi saat layar diubah ukurannya, misalnya dengan memutar iPad? Itu berpotensi mengubah tinggi tampilan koleksi, dan oleh karena itu, tinggi sel, tetapi jika di layar, sel belum tentu dimuat ulang oleh tampilan tabel, sehingga tidak pernah memanggil metode cellForRowAtIndexPath: dan tidak memberi Anda kesempatan untuk ubah konstanta batasan. Mungkin saja bisa memaksa reloadData.
Carl Lindberg
2
Sudahkah Anda mencoba ukuran sel collectionView yang berbeda? Itu masalah saya. Jika Anda memiliki ukuran sel collectionView yang berbeda, itu tidak berfungsi ... :(
Pablo Romeu
22

Baik tampilan tabel maupun tampilan koleksi adalah UIScrollViewsubkelas dan karenanya tidak suka disematkan di dalam tampilan gulir lain saat mereka mencoba menghitung ukuran konten, menggunakan kembali sel, dll.

Saya menyarankan Anda untuk menggunakan hanya tampilan koleksi untuk semua tujuan Anda.

Anda dapat membaginya menjadi beberapa bagian dan "memperlakukan" tata letak beberapa bagian sebagai tampilan tabel dan lainnya sebagai tampilan koleksi. Lagi pula, tidak ada yang tidak bisa Anda capai dengan tampilan koleksi yang Anda bisa dengan tampilan tabel.

Jika Anda memiliki tata letak kisi dasar untuk "bagian" tampilan koleksi, Anda juga dapat menggunakan sel tabel biasa untuk menanganinya. Namun jika Anda tidak memerlukan dukungan iOS 5, Anda harus menggunakan tampilan koleksi dengan lebih baik.

Rivera
sumber
1
Anda telah meletakkan "perlakukan" dalam tanda kutip, karena Anda TIDAK dapat menentukan tata letak yang berbeda per bagian CollectionView, bukan? Saya belum menemukan opsi untuk menentukan tata letak yang berbeda untuk bagian tampilan koleksi yang berbeda. Apakah saya mengabaikan sesuatu atau Anda berbicara tentang menanggapi secara berbeda untuk 'layoutAttributesForItemAtIndexPath' untuk bagian berbeda dalam subkelas kustom saya sendiri dari UICollectionViewLayout?
alex da franca
Ya -> Apakah Anda berbicara tentang menanggapi secara berbeda layoutAttributesForItemAtIndexPathuntuk bagian yang berbeda dalam subkelas khusus saya UICollectionViewLayout?
Rivera
2
@Rivera, jawaban Anda paling masuk akal dan terdengar benar. Saya telah membaca saran ini di banyak tempat. Bisakah Anda juga membagikan beberapa tautan untuk mengambil contoh atau membahas tentang cara mencapai itu atau setidaknya beberapa petunjuk. TIA
tanda musim panas ini
3
Jawaban Anda mengasumsikan Anda memulai dari awal, dan belum memiliki tampilan tabel besar yang rumit yang perlu Anda sesuaikan. Pertanyaan yang secara khusus ditanyakan tentang meletakkan collectionview dalam tableview. IMO tanggapan Anda bukanlah "jawaban"
xaphod
2
Ini jawaban yang buruk. Memiliki tampilan koleksi di dalam tampilan tabel adalah hal yang umum dilakukan, hampir setiap aplikasi melakukannya.
crashoverride777
10

Jawaban Pablo Romeu di atas ( https://stackoverflow.com/a/33364092/2704206 ) sangat membantu saya dengan masalah saya. Saya harus melakukan beberapa hal secara berbeda, bagaimanapun, agar ini bekerja untuk masalah saya. Pertama, saya tidak perlu layoutIfNeeded()sering menelepon . Saya hanya perlu memanggilnya collectionViewdi dalam systemLayoutSizeFittingfungsi.

Kedua, saya memiliki batasan tata letak otomatis pada tampilan koleksi saya di sel tampilan tabel untuk memberikan beberapa padding. Jadi saya harus mengurangi margin depan dan belakang dari targetSize.widthsaat mengatur collectionView.framelebar. Saya juga harus menambahkan margin atas dan bawah ke CGSizetinggi nilai pengembalian .

Untuk mendapatkan konstanta pembatas ini, saya memiliki opsi untuk membuat outlet ke pembatas, meng-hard-coding konstanta mereka, atau mencarinya dengan pengenal. Saya memutuskan untuk menggunakan opsi ketiga untuk membuat kelas sel tampilan tabel kustom saya dengan mudah dapat digunakan kembali. Pada akhirnya, ini adalah semua yang saya butuhkan untuk membuatnya berfungsi:

class CollectionTableViewCell: UITableViewCell {

    // MARK: -
    // MARK: Properties
    @IBOutlet weak var collectionView: UICollectionView! {
        didSet {
            collectionViewLayout?.estimatedItemSize = CGSize(width: 1, height: 1)
            selectionStyle = .none
        }
    }

    var collectionViewLayout: UICollectionViewFlowLayout? {
        return collectionView.collectionViewLayout as? UICollectionViewFlowLayout
    }

    // MARK: -
    // MARK: UIView functions
    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()

        let topConstraintConstant = contentView.constraint(byIdentifier: "topAnchor")?.constant ?? 0
        let bottomConstraintConstant = contentView.constraint(byIdentifier: "bottomAnchor")?.constant ?? 0
        let trailingConstraintConstant = contentView.constraint(byIdentifier: "trailingAnchor")?.constant ?? 0
        let leadingConstraintConstant = contentView.constraint(byIdentifier: "leadingAnchor")?.constant ?? 0

        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width - trailingConstraintConstant - leadingConstraintConstant, height: 1)

        let size = collectionView.collectionViewLayout.collectionViewContentSize
        let newSize = CGSize(width: size.width, height: size.height + topConstraintConstant + bottomConstraintConstant)
        return newSize
    }
}

Sebagai fungsi pembantu untuk mengambil batasan oleh pengenal, saya menambahkan ekstensi berikut:

extension UIView {
    func constraint(byIdentifier identifier: String) -> NSLayoutConstraint? {
        return constraints.first(where: { $0.identifier == identifier })
    }
}

CATATAN: Anda perlu menetapkan pengenal pada batasan ini di storyboard Anda, atau di mana pun batasan tersebut dibuat. Kecuali jika mereka memiliki konstanta 0, maka itu tidak masalah. Selain itu, seperti dalam tanggapan Pablo, Anda perlu menggunakan UICollectionViewFlowLayouttata letak untuk tampilan koleksi Anda. Terakhir, pastikan Anda menautkan collectionViewIBOutlet ke storyboard Anda.

Dengan sel tampilan tabel kustom di atas, saya sekarang dapat membuat subkelasnya di sel tampilan tabel lain yang memerlukan tampilan koleksi dan menerapkan protokol UICollectionViewDelegateFlowLayoutdan UICollectionViewDataSource. Semoga ini bisa membantu orang lain!

jmad8
sumber
5

Saya membaca semua jawaban. Ini sepertinya melayani semua kasus.

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()
        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width , height: 1)
        return collectionView.collectionViewLayout.collectionViewContentSize
}
SRP-Achiever
sumber
3

Alternatif untuk solusi Pablo Romeu adalah menyesuaikan UICollectionView itu sendiri, daripada melakukan pekerjaan dalam sel tampilan tabel.

Masalah yang mendasarinya adalah bahwa secara default tampilan koleksi tidak memiliki ukuran intrinsik sehingga tidak dapat menginformasikan tata letak otomatis dari dimensi yang akan digunakan. Anda bisa memperbaikinya dengan membuat subclass kustom yang mengembalikan ukuran intrinsik yang berguna.

Buat subclass UICollectionView dan ganti metode berikut

override func intrinsicContentSize() -> CGSize {
    self.layoutIfNeeded()

    var size = super.contentSize
    if size.width == 0 || size.height == 0 {
        // return a default size
        size = CGSize(width: 600, height:44)
    }

    return size
 }

override func reloadData() {
    super.reloadData()
    self.layoutIfNeeded()
    self.invalidateIntrinsicContentSize()
}

(Anda juga harus mengganti metode terkait: reloadSections, reloadItemsAtIndexPaths dengan cara yang mirip dengan reloadData ())

Memanggil layoutIfNeeded memaksa tampilan koleksi untuk menghitung ulang ukuran konten yang kemudian dapat digunakan sebagai ukuran intrinsik baru.

Selain itu, Anda perlu menangani perubahan ukuran tampilan secara eksplisit (misalnya pada rotasi perangkat) di pengontrol tampilan tabel

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
}
Lembah
sumber
bro bisakah kamu membantu masalah saya stackoverflow.com/questions/44650058/… ?
Mei Phyu
3

Saya menghadapi masalah yang sama baru-baru ini dan saya hampir mencoba setiap solusi dalam jawaban, beberapa di antaranya berhasil dan yang lainnya tidak menjadi perhatian utama saya tentang pendekatan @PabloRomeu adalah jika Anda memiliki konten lain di sel (selain tampilan koleksi) Anda harus menghitung tinggi dan tinggi batasannya dan mengembalikan hasilnya untuk mendapatkan tata letak otomatis yang benar dan saya tidak suka menghitung hal-hal secara manual dalam kode saya. Jadi, inilah solusi yang berfungsi dengan baik untuk saya tanpa melakukan perhitungan manual dalam kode saya.

dalam cellForRow:atIndexPathtampilan tabel saya melakukan hal berikut:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //do dequeue stuff
    //initialize the the collection view data source with the data
    cell.frame = CGRect.zero
    cell.layoutIfNeeded()
    return cell
}

Saya pikir apa yang terjadi di sini adalah saya memaksa sel tampilan tabel untuk menyesuaikan tingginya setelah ketinggian tampilan koleksi dihitung. (setelah memberikan tanggal collectionView ke sumber data)

Abd Al-rhman Taher Badary
sumber
2

Saya akan meletakkan metode statis pada kelas tampilan koleksi yang akan mengembalikan ukuran berdasarkan konten yang dimilikinya. Kemudian gunakan metode itu heightForRowAtIndexPathuntuk mengembalikan ukuran yang sesuai.

Perhatikan juga bahwa Anda bisa mendapatkan perilaku aneh saat menyematkan viewControllers semacam ini. Saya melakukannya sekali dan memiliki beberapa masalah ingatan aneh yang tidak pernah berhasil saya atasi.

InkGolem
sumber
Bagi saya, saya mencoba menyematkan pengontrol tampilan tabel di dalam pengontrol tampilan koleksi. Setiap kali sebuah sel digunakan kembali, itu berakhir dengan mengingat beberapa batasan autolayout yang saya terapkan padanya. Itu sangat fiddly dan akhirnya adalah ide yang buruk. Saya rasa saya hanya akan menggunakan tampilan koleksi tunggal.
fatuhoku
2

Mungkin varian saya akan berguna; Saya telah memutuskan tugas ini selama dua jam terakhir. Saya tidak menganggap itu 100% benar atau optimal, tetapi keahlian saya masih sangat kecil dan saya ingin mendengar komentar dari para ahli. Terima kasih. Satu catatan penting: ini berfungsi untuk tabel statis - ini ditentukan oleh pekerjaan saya saat ini. Jadi, yang saya gunakan hanyalah viewWillLayoutSubviews dari tableView . Dan sedikit lagi.

private var iconsCellHeight: CGFloat = 500 

func updateTable(table: UITableView, withDuration duration: NSTimeInterval) {
    UIView.animateWithDuration(duration, animations: { () -> Void in
        table.beginUpdates()
        table.endUpdates()
    })
}

override func viewWillLayoutSubviews() {
    if let iconsCell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 1)) as? CategoryCardIconsCell {
        let collectionViewContentHeight = iconsCell.iconsCollectionView.contentSize.height
        if collectionViewContentHeight + 17 != iconsCellHeight {
            iconsCellHeight = collectionViewContentHeight + 17
            updateTable(tableView, withDuration: 0.2)
        }
    }
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch (indexPath.section, indexPath.row) {
        case ...
        case (1,0):
            return iconsCellHeight
        default:
            return tableView.rowHeight
    }
}
  1. Saya tahu, bahwa collectionView terletak di baris pertama dari bagian kedua;
  2. Misalkan ketinggian baris adalah 17 p. lebih besar, dari tinggi isinya;
  3. iconsCellHeight adalah nomor acak saat program dimulai (saya tahu, bahwa dalam bentuk potret harus tepat 392, tetapi itu tidak penting). Jika konten collectionView + 17 tidak sama dengan angka ini, ubah nilainya. Lain kali dalam situasi ini kondisi memberikan SALAH;
  4. Setelah semua perbarui tableView. Dalam kasus saya ini adalah kombinasi dari dua operasi (untuk pembaruan yang bagus dari baris yang diperpanjang);
  5. Dan tentu saja, di heightForRowAtIndexPath tambahkan satu baris ke kode.
Ilya A. Shuvaloff
sumber
2

Pendekatan termudah yang saya temukan, sejauh ini, Kredit untuk jawaban @igor di atas,

Di kelas tableviewcell Anda cukup masukkan ini

override func layoutSubviews() {
    self.collectionViewOutlet.constant = self.postPoll.collectionViewLayout.collectionViewContentSize.height
}

dan tentu saja, ubah collectionviewoutlet dengan outlet Anda di kelas sel

Osa
sumber
1
Tinggi sel tidak dihitung dengan benar
Nik Kov
2

Saya mendapatkan ide dari postingan @Igor dan menginvestasikan waktu saya untuk proyek ini dengan cepat

Baru saja melewati ini di

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //do dequeue stuff
    cell.frame = tableView.bounds
    cell.layoutIfNeeded()
    cell.collectionView.reloadData()
    cell.collectionView.heightAnchor.constraint(equalToConstant: cell.collectionView.collectionViewLayout.collectionViewContentSize.height)
    cell.layoutIfNeeded()
    return cell
}

Tambahan: Jika Anda melihat UICollectionView Anda berombak saat memuat sel.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {       
  //do dequeue stuff
  cell.layer.shouldRasterize = true
  cell.layer.rasterizationScale = UIScreen.main.scale
  return cell
}
Nazmul Hasan
sumber
0

Solusi Pablo tidak berfungsi dengan baik untuk saya, saya memiliki efek visual yang aneh (collectionView tidak menyesuaikan dengan benar).

Apa yang berhasil adalah menyesuaikan batasan tinggi collectionView (sebagai NSLayoutConstraint) ke collectionView contentSize selama layoutSubviews(). Ini adalah metode yang dipanggil saat autolayout diterapkan ke sel.

// Constraint on the collectionView height in the storyboard. Priority set to 999.
@IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!


// Method called by autolayout to layout the subviews (including the collectionView).
// This is triggered with 'layoutIfNeeded()', or by the viewController
// (happens between 'viewWillLayoutSubviews()' and 'viewDidLayoutSubviews()'.
override func layoutSubviews() {

    collectionViewHeightConstraint.constant = collectionView.contentSize.height
    super.layoutSubviews()
}

// Call `layoutIfNeeded()` when you update your UI from the model to trigger 'layoutSubviews()'
private func updateUI() {
    layoutIfNeeded()
}
Frédéric Adda
sumber
-3

Di UITableViewDelegate Anda:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return ceil(itemCount/4.0f)*collectionViewCellHeight;
}

Gantikan itemCount dan CollectionViewCellHeight dengan nilai sebenarnya. Jika Anda memiliki array itemCount array mungkin:

self.items[indexPath.row].count

Atau terserah.

Martin
sumber
Saya pikir pertanyaan utamanya adalah bagaimana menghitung collectionViewCellHeight sebelum dirender.
tanda musim panas ini
-3

1.Buat sel tiruan.
2. Gunakan metode collectionViewContentSize pada UICollectionViewLayout dari UICollectionView menggunakan data saat ini.

Parag Shinde
sumber
Ini harus menjadi jawaban terbaik ... karena tidak ada kemungkinan untuk menyetel tinggi sel dengan 'uicollectionview' tanpa meletakkan konten ke sel tiruan, mendapatkan tinggi, dan kemudian menyetelnya lagi ke sel yang tepat
Bartłomiej Semańczyk
bagaimana cara menggunakan metode itu?
xtrinch
Tambahkan contoh.
Nik Kov
-5

Anda dapat menghitung ketinggian koleksi berdasarkan sifat-sifatnya seperti itemSize, sectionInset, minimumLineSpacing, minimumInteritemSpacing, jika Anda collectionViewCellmemiliki perbatasan aturan.

sablib
sumber