动态大小 CollectionViewCells

Posted

技术标签:

【中文标题】动态大小 CollectionViewCells【英文标题】:Dynamic Size CollectionViewCells 【发布时间】:2018-09-25 01:19:49 【问题描述】:

我有一个布局,它使用多个 collectionviewcells 来布置自己。目前我使用的是静态高度,但众所周知,在我的情况下,特别是在我的情况下,不知道内容的大小,因为它将是占据大部分单元格的文本。我一直无法找到一种准确的方法来根据单元格中 textView 的大小以及填充来调整单元格的大小。

所以简而言之,我要问的是,是否有根据 collectionVIew 中事物的大小来调整内容的大小。

这是我目前拥有的单元格

import UIKit

class DetailCell: UICollectionViewCell 

    var eventDescription: String? 
        didSet
            print("got description")
            guard let eventDescription = eventDescription else 
                return
            
            eventDetails.text = eventDescription
            updateWithSpacing(lineSpacing: 10.0)
            textViewDidChange(eventDetails)

        
    




    lazy var eventDetails: UITextView = 
        let textView = UITextView()
        guard let customFont = UIFont(name: "NoirPro-SemiBold", size: 15) else 
            fatalError("""
        Failed to load the "CustomFont-Light" font.
        Make sure the font file is included in the project and the font name is spelled correctly.
        """
            )
        
        textView.font = customFont
        textView.textColor = UIColor.rgb(red: 32, green: 32, blue: 32)
        textView.textContainer.maximumNumberOfLines = 0
        textView.isScrollEnabled = false
        textView.isEditable = false
        textView.textAlignment = .natural
        return textView
    ()


    override init(frame: CGRect) 
        super.init(frame: frame)
        setupViews()
    

    fileprivate func setupViews()
        addSubview(eventDetails)
        eventDetails.delegate = self

        eventDetails.snp.makeConstraints 
            make in
            make.top.equalTo(detailsLabel.snp.bottom).offset(15)
            make.left.right.equalTo(self).inset(5)
            make.height.equalTo(50)
        

    

    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    


    //MARK: - Update Line Spacing
    func updateWithSpacing(lineSpacing: Float) 
        // The attributed string to which the
        // paragraph line spacing style will be applied.
        let attributedString = NSMutableAttributedString(string: eventDetails.text!)
        let mutableParagraphStyle = NSMutableParagraphStyle()
        // Customize the line spacing for paragraph.
        mutableParagraphStyle.lineSpacing = CGFloat(lineSpacing)
        mutableParagraphStyle.alignment = .justified
        if let stringLength = eventDetails.text?.count 
            attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value: mutableParagraphStyle, range: NSMakeRange(0, stringLength))
        
        // textLabel is the UILabel subclass
        // which shows the custom text on the screen
        eventDetails.attributedText = attributedString

    



extension DetailCell: UITextViewDelegate 
    func textViewDidChange(_ textView: UITextView) 
        print(textView.text)
        let size = CGSize(width: self.frame.width - 5, height: .infinity)
        let estimatedSize = textView.sizeThatFits(size)
        textView.constraints.forEach  (constraint) in
            if constraint.firstAttribute == .height 
                constraint.constant = estimatedSize.height
            
        
    


这是我的单元格尺寸。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
        return CGSize(width: collectionView.frame.width, height: 350.0)

任何帮助将不胜感激

【问题讨论】:

【参考方案1】:

你可以自己找出单元格的高度

extension String 
func height(withConstrainedWidth width: CGFloat, font: UIFont?) -> CGFloat 
    guard let fontValue = font else 
        return 0
    
    let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
    let boundingBox = self.boundingRect(with: constraintRect,
                                        options: .usesLineFragmentOrigin,
                                        attributes: [NSFontAttributeName: fontValue],
                                        context: nil)
    if boundingBox.height >= 80 
       return 80
    
    return ceil(boundingBox.height)
 

之后,您可以使用此字符串扩展来获取高度值并将其传递给 collectionView 委托

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize 
    let feature = cellData.arrayOfData[indexPath.row]
    let height = feature.height(withConstrainedWidth: collectionView.frame.width,
                                font:"FontYouAddedToTextView")
    return CGSize(width: collectionView.frame.width, height: height)

【讨论】:

以上是关于动态大小 CollectionViewCells的主要内容,如果未能解决你的问题,请参考以下文章

动态模拟 iOS 动态类型系统文本大小 (UIContentSizeCategory)

前端-根据页面大小动态计算字体大小

Duilib如何动态修改字体大小

根据内容大小动画和调整 div 动态高度

Java 如何动态改变改变组件大小(更随窗口) 和 根据窗口大小改变程序窗口大小f

如何动态调整 UIScrollView 的大小?