【问题标题】:How to get the correct frame size of UICollectionView within UITableViewCell?如何在 UITableViewCell 中获取 UICollectionView 的正确帧大小?
【发布时间】:2022-01-03 05:57:58
【问题描述】:

目标

我正在尝试在 iOS 15 中克隆以下新闻源布局:

我的实现

PostCellUITableViewCell 的子类,ImageGridCollectionViewContentSizeFitCollectionView 的子类(启用动态高度)。

class ContentSizeFitCollectionView: UICollectionView {
    override var contentSize: CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }
    
    override var intrinsicContentSize: CGSize {
        layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    }
}

ImageGridCollectionView 是用UICollectionViewFlowLayout 实现的,其委托方法如下:

extension ImageGridCollectionView: UICollectionViewDelegateFlowLayout {
    private func getItemSize(width: FractionalLength, height: FractionalLength) -> CGSize {
        let screenWidth = self.frame.size.width
        let itemWidth: CGFloat = (screenWidth - spacing * (1 / width.fractionalValue - 1)) * width.fractionalValue
        let itemHeight: CGFloat = screenWidth * height.fractionalValue
        return CGSize(width: itemWidth, height: itemHeight)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let item = indexPath.item
        switch numberOfImages {
        case 1:
            return getItemSize(width: .one, height: .threeFourths)
        case 2:
            return getItemSize(width: .oneHalf, height: .threeFourths)
        case 3:
            if item < 1 {
                return getItemSize(width: .one, height: .oneHalf)
            } else {
                return getItemSize(width: .oneHalf, height: .oneHalf)
            }
        case 4:
            return getItemSize(width: .oneHalf, height: .oneHalf)
        default:
            if item < 2 {
                return getItemSize(width: .oneHalf, height: .oneHalf)
            } else {
                return getItemSize(width: .oneThird, height: .oneThird)
            }
        }
    }
}

PostCell 中,实现了ImageGridCollectionView 的自动布局:

contentView.addSubview(imageGridCollectionView)
NSLayoutConstraint.activate([
            imageGridCollectionView.topAnchor.constraint(equalTo: textContentLabel.bottomAnchor, constant: .standardTopMargin),
            imageGridCollectionView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            imageGridCollectionView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            statHorizontalStackView.topAnchor.constraint(equalTo: imageGridCollectionView.bottomAnchor, constant: .standardTopMargin),
            ...
        ])

问题

上面实现的问题是,在计算collectionView的流布局时,collectionView正在访问getItemSize(width:height:)中的self.frame,也就是访问时的(-32783.0, 0.0, 65566.0, 0.0)

因此,itemHeight 是根据巨大的screenWidth(65566.0) 计算得出的。

我尝试过的解决方案

UIStackView 包裹imageGridCollectionView 有点效果(虽然不完美;高度偶尔会变为零):

let stack = UIStackView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.addArrangedSubview(imageGridCollectionView)
contentView.addSubview(stack)
NSLayoutConstraint.activate([
      stack.topAnchor.constraint(equalTo: textContentLabel.bottomAnchor, constant: .standardTopMargin),
      stack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
      stack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
])

但我想要一个更简洁的解决方案而不是这种解决方法,或者至少了解它为什么有效。

我想知道 TableViewCells 中是否有类似viewDidLayoutSubviews 的内容,以便我可以轻松访问更新的帧大小。

任何帮助将不胜感激。 谢谢。

【问题讨论】:

标签: ios swift uitableview uicollectionview


【解决方案1】:

我找到了解决方案。 layoutIfNeeded 是关键。

PostCell

    func configureCell(with post: Post) {
        commentCountLabel.text = "\(post.comments.withCommas(unit: "개"))"
        likeCountLabel.text = post.likes.withCommas(unit: "개")
        textContentLabel.text = post.content
        self.layoutIfNeeded()  // important
    }

这解决了所有问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    • 2019-09-04
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多