Bir UITableViewCell içindeki UICollectionView - dinamik yükseklik?


125

Uygulama ekranlarımızdan biri, UICollectionViewbir UITableViewCell. Bu UICollectionView, dinamik olarak hesaplanması gereken bir yükseklikle sonuçlanan dinamik sayıda öğeye sahip olacaktır. Ancak gömülü olanın yüksekliğini hesaplamaya çalışırken sorunlarla karşılaşıyorum UICollectionView.

Kapsamımız UIViewControllerStoryboard'larda oluşturuldu ve otomatik mizanpajı kullanıyor. Ama dinamik yüksekliğini artırmak için nasıl bilmiyorum UITableViewCellyüksekliğine dayalı UICollectionView.

Bunu nasıl başaracağınıza dair ipucu veya tavsiye veren var mı?


başarmaya çalıştığınız düzen hakkında biraz daha bilgi verebilir misiniz? Yüksekliği UITableViewCellkeskin masa görünümünden farklı mı? Her iki dikey kaydırma gerekiyor mu UICollectionViewveUITableView
apouche

3
UITableViewCell yüksekliğinin, tablo görünümü hücresinin parçası olan UICollectionView yüksekliğine bağlı olarak dinamik olması beklenir. UICollectionView'umun düzeni 4 sütun ve dinamik satır sayısıdır. Yani, 100 öğe ile UICollectionView'umda 4 sütun ve 25 satır olacaktı. Belirli bir hücrenin yüksekliği - UITableView'ın heightForRowAtIndexPath tarafından belirtildiği gibi - o UICollectionView boyutuna göre ayarlanabilmelidir. Bu biraz daha açık mı?
Shadowman

@Shadowman, lütfen bana bu durum için bir çözüm öner
Ravi Ojha

Yanıtlar:


127

Doğru cevap EVET , bunu YAPABİLİRSİNİZ .

Bu problemle birkaç hafta önce karşılaştım. Aslında düşündüğünüzden daha kolay. Hücrelerinizi NIB'lere (veya hikaye tahtalarına) yerleştirin ve otomatik düzenin tüm işi yapmasına izin vermek için onları sabitleyin

Aşağıdaki yapı göz önüne alındığında:

Tablo görünümü

TableViewCell

CollectionView

CollectionViewCell

CollectionViewCell

CollectionViewCell

[... değişken sayıda hücre veya farklı hücre boyutları]

Çözüm, auto layout'a önce collectionViewCell boyutlarını hesaplamasını, ardından koleksiyonun contentSize boyutunu hesaplamasını ve bunu hücrenizin boyutu olarak kullanmasını söylemektir. Bu, "sihir yapan" UIView yöntemidir:

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

Burada, sizin durumunuzda CollectionView'un contentSize olan TableViewCell'in boyutunu ayarlamanız gerekir.

CollectionViewCell

At CollectionViewCell Eğer modelini değiştirmek her zaman düzeni için hücreyi anlatmak zorunda (örn: bir metin ile bir UILabel ayarlayın, ardından hücre yeniden düzen olmak zorundadır).

- (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

TableViewCell büyü yapar. Bu sizin CollectionView'ın için bir çıkışa sahiptir kullanarak CollectionView'ın hücreleri için otomatik düzenini sağlayan estimatedItemSize ait UICollectionViewFlowLayout .

Daha sonra işin püf noktası , tableView hücrenizin boyutunu systemLayoutSizeFittingSize ... yönteminde ayarlamaktır. (NOT: iOS8 veya üzeri)

NOT: Ben tableView delegesi hücrenin yüksekliği yöntemini kullanmaya çalıştı -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath.ama çok geç CollectionView contentSize hesaplamak için otomatik düzen sisteminin ve bazen yanlış boyutlandýrýlmýþ hücreleri bulabilirsiniz.

@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

TableViewController'ınızda tableView hücreleri için otomatik düzen sistemini etkinleştirmeyi unutmayın :

- (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;

}

KREDİ: @rbarbera bunu çözmemize yardımcı oldu


4
Evet. Bu çalışıyor. Kabul edilen cevap bu olmalıdır.
csotiriou

1
Herhangi bir kuruluş bana bunun için bir örnek kod verebilir mi? tablo görünümü hücresinin içindeki dikey koleksiyon görünümünde birden çok resmi göstermek istiyorum ..
Ravi Ojha

4
Sonunda bu benim için çalıştı, ancak başka bir numara yapmam gerekiyordu: cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);Bu, uzun bir collectionView ile uzun bir hücreyi "simüle edecek", böylece collectionView tüm hücrelerinin boyutunu hesaplayacaktır. Aksi takdirde, collectionView yalnızca görünür hücre boyutlarını hesapladı ve talbeViewCell yüksekliğini yanlış ayarladı.
ingaham

20
çerçeve yüksekliğini maksimum olarak systemLayoutSizeFittingSizeayarlarken, hücreyi yeniden yüklerken hızlı bir soruna çarptım, uygulamalar self.collectionView.layoutIfNeeded(). Çerçeve yüksekliğini maksimum yükseklik yerine 1 ayarlayarak sabitledim. Herhangi biri bu soruna rastlarsa yardımcı olacağını umuyoruz.
titan

6
İşte benim için düzeltilen şey - systemLayoutSizeFittingşu anda yanıtta gösterilen sırayı tersine çevirin, böylece önce collectionView.layoutIfNeeded()çalışır, sonracollectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
xaphod

101

Çözümümün @PabloRomeu tarafından önerilenden çok daha basit olduğunu düşünüyorum.

Adım 1. Nereye yerleştirildiği UICollectionViewiçin bir çıkış oluşturun . Bırak, adı olacakUITableViewCell subclassUICollectionViewcollectionView

Adım 2. UICollectionViewYükseklik kısıtlaması için IB'yi ekleyin ve çıkış UITableViewCell subclassda yaratın . Bırakın adı olacak collectionViewHeight.

Adım 3. tableView:cellForRowAtIndexPath:Kodu ekleyin:

// deque a cell
cell.frame = tableView.bounds;
[cell layoutIfNeeded];
[cell.collectionView reloadData];
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height;

1
Bunu gerçekten denedin mi? Hem koleksiyon görünümünde bir yükseklik sınırlaması ayarlamak hem de bunu tablo görünümü hücresinin kenar boşluklarına sabitlemek mümkün görünmüyor. Ya çok az kısıtlamayla karşılaşırsınız (dolayısıyla sıfır boyut uyarısı) ya da çakışan kısıtlamalarla karşılaşırsınız (bunlardan biri yok sayılır). Lütfen bu çözüm için kısıtlamaların nasıl ayarlanacağını açıklayın.
Dale

2
Çalıştım. collectionViewTüm taraflar için kısıtlamalar ekliyorum UITableViewCellve ayarlıyorum tableView.estimatedRowHeight = 44;vetableView.rowHeight = UITableViewAutomaticDimension;
Igor

3
Bu şampiyon gibi çalışıyor ... basit ve verimli ... teşekkürler. Birisi için çalışmıyorsa, muhtemelen nedeni olabilir, koleksiyon görünümünün altını tablo görünümü hücresinin altına bağlamamız gerekir. Sonra çalışmaya başlayacak. Mutlu kodlama .. :)
Sebin Roy

2
Bu, ekran yeniden boyutlandırıldığında, örneğin bir iPad döndürüldüğünde çalışır mı? Bu, potansiyel olarak koleksiyon görünümünün yüksekliğini ve dolayısıyla hücrenin yüksekliğini değiştirebilir, ancak ekranda hücre mutlaka tablo görünümü tarafından yeniden yüklenmeyebilir, bu nedenle hiçbir zaman cellForRowAtIndexPath: yöntemini çağırmaz ve size bir şans vermez. kısıtlama sabitini değiştirin. Yine de bir yeniden yükleme Verisini zorlamak mümkün olabilir.
Carl Lindberg

2
Farklı collectionView hücre boyutlarını denediniz mi? Benim sorunum buydu. Farklı collectionView hücre boyutlarına sahipseniz, işe yaramadı ... :(
Pablo Romeu

22

Hem tablo görünümleri hem de koleksiyon görünümleri UIScrollViewalt sınıflardır ve bu nedenle içerik boyutlarını hesaplamaya, hücreleri yeniden kullanmaya vb. Çalışırken başka bir kaydırma görünümünün içine yerleştirilmekten hoşlanmazlar.

Tüm amaçlarınız için yalnızca bir koleksiyon görünümü kullanmanızı tavsiye ederim.

Bunu bölümlere ayırabilir ve bazı bölümlerin düzenini bir tablo görünümü ve diğerlerini bir koleksiyon görünümü olarak "ele alabilirsiniz". Sonuçta, bir tablo görünümüyle yapabileceğiniz bir koleksiyon görünümüyle elde edemeyeceğiniz hiçbir şey yok.

Koleksiyon görünümü "parçalarınız" için temel bir ızgara düzeniniz varsa, bunları işlemek için normal tablo hücrelerini de kullanabilirsiniz. Yine de iOS 5 desteğine ihtiyacınız yoksa, koleksiyon görünümlerini daha iyi kullanmalısınız.


1
Alıntılara "muamele" koydunuz, çünkü her CollectionView bölümü için farklı düzenler tanımlayamazsınız, değil mi? Farklı koleksiyon görünümü bölümleri için farklı düzenler tanımlama seçeneği bulamadım. Bir şeyi gözden mi atıyorum yoksa UICollectionViewLayout'un kendi özel alt sınıfımdaki farklı bölümler için 'layoutAttributesForItemAtIndexPath' e farklı şekilde yanıt vermekten mi bahsediyorsunuz?
alex da franca

Evet -> layoutAttributesForItemAtIndexPathKendi özel alt sınıfımdaki farklı bölümlere farklı yanıt vermekten mi bahsediyorsunuz UICollectionViewLayout?
Rivera

2
@Rivera, cevabınız çok mantıklı ve kulağa doğru geliyor. Bu öneriyi birçok yerde okudum. Ayrıca bunu nasıl başaracağınıza dair örnekleme veya en azından bazı ipuçları paylaşabilir misiniz? TIA
thesummersign

3
Cevabınız, sıfırdan başladığınızı ve uymanız gereken büyük karmaşık bir tablo görünümüne sahip olmadığınızı varsayar. Soru özellikle bir koleksiyon görünümünün tablo görünümüne yerleştirilmesi hakkında soruldu. IMO cevabınız bir "cevap" değil
xaphod

2
Bu kötü bir cevap. Tablo görünümlerinin içinde koleksiyon görünümlerine sahip olmak, yapılacak çok yaygın bir şeydir, neredeyse her uygulama bunu yapar.
crashoverride777

10

Pablo Romeu'nun yukarıdaki cevabı ( https://stackoverflow.com/a/33364092/2704206 ) sorunumda bana çok yardımcı oldu. Bununla birlikte, bunun benim sorunum için çalışmasını sağlamak için birkaç şeyi farklı yapmak zorunda kaldım. Öncelikle, layoutIfNeeded()sık sık aramak zorunda değildim . Ben sadece onu aramak zorunda collectionViewiçinde systemLayoutSizeFittingişlevi.

İkinci olarak, tablo görünümü hücresindeki koleksiyon görünümümde ona biraz dolgu sağlamak için otomatik düzen kısıtlamalarım vardı. Bu yüzden baştaki ve sondaki kenar boşluklarınıtargetSize.widthcollectionView.frame genişliğini ayarlarken . Ayrıca dönüş değeri CGSizeyüksekliğine üst ve alt kenar boşluklarını eklemem gerekiyordu .

Bu kısıtlama sabitlerini elde etmek için ya kısıtlamalara çıkışlar oluşturma, sabitlerini sabit kodlama ya da bir tanımlayıcı ile arama seçeneklerim vardı. Özel tablo görünümü hücre sınıfımı kolayca yeniden kullanılabilir hale getirmek için üçüncü seçeneği kullanmaya karar verdim. Sonunda, onu çalıştırmak için ihtiyacım olan her şey buydu:

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
    }
}

Tanımlayıcıya göre bir kısıtlama almak için yardımcı bir işlev olarak, aşağıdaki uzantıyı ekliyorum:

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

NOT: Film şeridinizde veya nerede oluşturuluyor olurlarsa olsunlar bu kısıtlamalara ilişkin tanımlayıcıyı ayarlamanız gerekecektir. 0 sabitine sahip olmadıkları sürece önemli değil. Ayrıca, Pablo'nun yanıtında UICollectionViewFlowLayoutolduğu gibi, koleksiyon görünümünüz için düzen olarak kullanmanız gerekecek . Son olarak, collectionViewIBOutlet'i film şeridinize bağladığınızdan emin olun .

Yukarıdaki özel tablo görünümü hücresiyle, artık onu bir koleksiyon görünümüne ihtiyaç duyan ve UICollectionViewDelegateFlowLayoutve UICollectionViewDataSourceprotokollerini uygulayan herhangi bir diğer tablo görünümü hücresinde alt sınıflara ayırabilirim . Umarım bu başka birine yardımcı olur!


5

Tüm cevapları okudum. Bu tüm davalara hizmet ediyor gibi görünüyor.

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
}

3

Pablo Romeu'nun çözümüne bir alternatif, işi tablo görünümü hücresinde yapmak yerine UICollectionView'ün kendisini özelleştirmektir.

Temel sorun, bir koleksiyon görünümünün varsayılan olarak iç boyuta sahip olmaması ve bu nedenle kullanılacak boyutların otomatik düzenini bilgilendirememesidir. Yararlı bir iç boyut döndüren özel bir alt sınıf oluşturarak bunu düzeltebilirsiniz.

UICollectionView alt sınıfını oluşturun ve aşağıdaki yöntemleri geçersiz kılın

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()
}

(İlgili yöntemleri de geçersiz kılmalısınız: reloadSections, reloadItemsAtIndexPaths, reloadData () 'ya benzer şekilde)

LayoutIfNeeded çağrısı, koleksiyon görünümünü daha sonra yeni iç boyut olarak kullanılabilecek içerik boyutunu yeniden hesaplamaya zorlar.

Ayrıca, tablo görünümü denetleyicisinde görünüm boyutundaki değişiklikleri (ör. Cihaz döndürmede) açıkça işlemeniz gerekir.

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
}

kardeşim lütfen stackoverflow.com/questions/44650058/… sorunuma yardım eder misin ?
Mayıs Phyu

3

Son zamanlarda aynı sorunla karşı karşıyaydım ve cevaplarda neredeyse her çözümü denedim, bazıları çalıştı ve diğerleri @PabloRomeu ile ilgili asıl endişem olmadı yaklaşımı ile , hücrede başka içerikler varsa (koleksiyon görünümü dışında) Otomatik düzeni doğru yapmak için onların yüksekliklerini ve sınırlamalarının yüksekliğini hesaplamanız ve sonucu döndürmeniz gerekecek ve ben de kodumda işleri manuel olarak hesaplamayı sevmiyorum. İşte kodumda herhangi bir manuel hesaplama yapmadan benim için iyi çalışan çözüm.

içinde cellForRow:atIndexPathtablo görünümünün ben aşağıdakileri yapın:

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
}

Sanırım burada olan şey, tablo görünümü hücresini koleksiyon görünümü yüksekliği hesaplandıktan sonra yüksekliğini ayarlamaya zorlamamdır. (collectionView tarihini veri kaynağına sağladıktan sonra)


2

Koleksiyon görünümü sınıfına, sahip olacağı içeriğe göre bir boyut döndürecek statik bir yöntem koyardım. Ardından heightForRowAtIndexPath, uygun boyutu döndürmek için bu yöntemi içinde kullanın .

Ayrıca, bu tür viewControllers'ı gömdüğünüzde bazı garip davranışlar alabileceğinizi unutmayın. Bir kez yaptım ve hiç çalışmadığım bazı garip hafıza sorunlarım vardı.


Benim için, koleksiyon görünümü denetleyicilerinin içine bir tablo görünümü denetleyicisi yerleştirmeye çalışıyordum. Bir hücre her yeniden kullanıldığında, onlara uyguladığım bazı otomatik düzen kısıtlamalarını hatırladı. Çok zordu ve nihayetinde korkunç bir fikirdi. Sanırım bunun yerine tek bir koleksiyon görünümü kullanacağım.
fatuhoku

2

Belki benim varyantım faydalı olacaktır; Bu göreve son iki saattir karar veriyorum. % 100 doğru veya optimal olduğunu düşünmüyorum, ancak becerim henüz çok küçük ve uzmanlardan gelen yorumları duymak istiyorum. Teşekkür ederim. Önemli bir not: bu statik tablo için çalışıyor - mevcut çalışmamla belirtiliyor. Yani, tüm ben kullanımıdır viewWillLayoutSubviews arasında tableView . Ve biraz daha fazlası.

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. CollectionView ikinci bölümün ilk satırında yer aldığını biliyorum;
  2. Satırın yüksekliği 17 p olsun. içerik yüksekliğinden daha büyük;
  3. iconsCellHeight, program başladığında rastgele bir sayıdır (portre biçiminde tam olarak 392 olması gerektiğini biliyorum, ancak önemli değil). CollectionView + 17'nin içeriği bu sayıya eşit değilse, değerini değiştirin. Bu durumda bir dahaki sefere koşul YANLIŞ verir;
  4. Sonuçta tableView'i güncelleyin. Benim durumumda, iki işlemin birleşimi (genişleyen satırların güzel güncellenmesi için);
  5. Ve tabii ki, heightForRowAtIndexPath'de koda bir satır ekleyin.

2

Şimdiye kadar bulduğum en kolay yaklaşım, yukarıdaki @igor cevabına Krediler,

Tableviewcell sınıfınıza şunu ekleyin

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

ve tabii ki, koleksiyon görünüm çıkışını hücrenin sınıfındaki prizinizle değiştirin


1
Hücrenin yüksekliği doğru hesaplanmıyor
Nik Kov

2

@ Igor gönderisinden fikir alıyorum ve hızlı bir şekilde projem için buna zaman ayırıyorum

Bunu senin içinde geç

 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
}

Ekleme: Hücreleri yüklerken UICollectionView dalgalı görüyorsanız.

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

0

Pablo'nun çözümü benim için pek işe yaramadı, tuhaf görsel efektlerim vardı (collectionView doğru şekilde ayarlanmıyordu).

İşe yarayan şey layoutSubviews(),. Bu, hücreye otomatik düzen uygulandığında çağrılan yöntemdir.

// 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()
}

-3

UITableViewDelegate'inizde:

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

İtemCount ve CollectionViewCellHeight değerlerini gerçek değerlerle değiştirin. Bir dizi diziniz varsa, itemCount şöyle olabilir:

self.items[indexPath.row].count

Ya da her neyse.


Bence asıl soru, collectionViewCellHeight işlenmeden önce nasıl hesaplanacağıdır .
thesummersign

-3

1. Sahte hücre oluşturun.
2. Şu anki verileri kullanarak UICollectionViewLayout of UICollectionViewLayout üzerinde collectionViewContentSize yöntemini kullanın.


Bu en iyi cevap olmalı ... çünkü içeriği sahte hücreye koymadan hücrenin yüksekliğini 'uicollectionview' ile ayarlama, yüksekliği alma ve sonra tekrar uygun hücreye ayarlama imkanı olmadığından
Bartłomiej Semańczyk

bu yöntemi nasıl kullanırım?
xtrinch

Bir örnek ekleyin.
Nik Kov

-5

Sen gibi kendi özelliklerine dayanarak koleksiyonun yüksekliğini hesaplayabilir itemSize, sectionInset, minimumLineSpacing, minimumInteritemSpacing, eğer senin collectionViewCellbir kuralın kenarlığı vardır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.