【问题标题】:Swift: Dynamically Size UICollectionViewCellSwift:动态调整 UICollectionViewCell 的大小
【发布时间】:2018-08-04 21:58:30
【问题描述】:

请不要将此标记为复制问题,因为此处的解决方案似乎不起作用。

我正在尝试根据文本的高度调整 UICollectionViewCell 的高度。出于某种奇怪的原因,文本的高度非常乱。我在 hereherehere 的帖子中采用了各种解决方案,但在我的情况下都不起作用。

我的方法涉及自动布局,我认为这不是促成因素。到目前为止我的代码:

class ChatBubbleCollectionViewCell: UICollectionViewCell {

    let textView: UITextView = {
        let tv = UITextView()
        tv.translatesAutoresizingMaskIntoConstraints = false
        tv.backgroundColor = .lightGray
        tv.font = UIFont.systemFont(ofSize: 17)
        tv.isScrollEnabled = false
        tv.isEditable = false
        tv.sizeToFit()
        tv.contentInset.top = -4
        return tv
    }()

    let bubbleView: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.layer.cornerRadius = 8
        return v
    }()

    var bubbleWidthAnchor: NSLayoutConstraint!
    var bubbleLeftAnchor: NSLayoutConstraint!
    var bubbleRightAnchor: NSLayoutConstraint!

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

        setupViews()

        backgroundColor = .blue
    }

    func setupViews() {
        addSubview(bubbleView)
        addSubview(textView)

        bubbleView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        bubbleView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

        let viewWidth = UIScreen.main.bounds.width

        bubbleWidthAnchor = bubbleView.widthAnchor.constraint(equalToConstant: viewWidth * 0.8)
        bubbleWidthAnchor.isActive = true

        bubbleLeftAnchor = bubbleView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8)
        bubbleLeftAnchor.isActive = false

        bubbleRightAnchor = bubbleView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -8)
        bubbleRightAnchor.isActive = true

        textView.topAnchor.constraint(equalTo: bubbleView.topAnchor, constant: 4).isActive = true
        textView.leftAnchor.constraint(equalTo: bubbleView.leftAnchor, constant: 4).isActive = true
        textView.rightAnchor.constraint(equalTo: bubbleView.rightAnchor, constant: -4).isActive = true
        textView.bottomAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: -4).isActive = true
    }

//At UICollectionViewController
 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ChatBubbleCollectionViewCell
        let item = messages[indexPath.item]

        if item.fromUserUID == fromUserUID {
            cell.bubbleView.backgroundColor = .customPink
            cell.textView.text = item.message
            cell.textView.textColor = .white
            cell.bubbleLeftAnchor.isActive = false
            cell.bubbleRightAnchor.isActive = true
        } else {
            cell.bubbleView.backgroundColor = .faintGray
            cell.textView.text = item.message
            cell.textView.textColor = .black
            cell.bubbleLeftAnchor.isActive = true
            cell.bubbleRightAnchor.isActive = false
        }

        cell.bubbleWidthAnchor.constant = estimatedFrame(for: item.message!).width 

        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        var height: CGFloat = 0

        if let text = messages[indexPath.item].message {
            height = ceil(estimatedFrame(for: text).height)
        }

        return CGSize(width: view.frame.width, height: height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 10
    }

    func estimatedFrame(for text: String) -> CGRect {
        let screenWidthDownsize = UIScreen.main.bounds.width * 0.8
        let size = CGSize(width: screenWidthDownsize, height: CGFloat.greatestFiniteMagnitude)
        let boundingBox = NSString(string: text).boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 17)], context: nil)
        return boundingBox
    }

以上代码给出以下结果:

如果我在高度上加上 50 来扩展单元格,就像height = ceil(estimatedFrame(for: text).height) + 50 那样,结果给出:

从图像中,我想人们可以观察到 boundingBox 并没有真正给出正确的值?有人能帮我指出正确的方向吗?谢谢

【问题讨论】:

  • 有可能当你在你的估计框架函数内将宽度设置为 80% 时,你没有考虑 UITextView 中的填充,并且 textview 中的可用宽度与 80 之间的细微差别% 计算导致计算的高度不同。
  • @Steve 谢谢史蒂夫,你的眼睛真的很敏锐。基本上我删除了所有的 paddings 和 edgeInsets,结果好多了。此后添加一些随机常数进行微调。
  • 乐于助人。介意我做一个答案,这样你就可以让它成为公认的解决方案吗?
  • @Steve 当然!非常感谢

标签: swift


【解决方案1】:

有可能当您在估计框架函数内将宽度设置为 80% 时,您没有考虑 UITextView 中的填充,并且 textview 中可用宽度与 80% 计算的细微差别导致正在计算不同的高度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多