【发布时间】:2022-01-03 05:57:58
【问题描述】:
目标
我正在尝试在 iOS 15 中克隆以下新闻源布局:
我的实现
PostCell 是 UITableViewCell 的子类,ImageGridCollectionView 是 ContentSizeFitCollectionView 的子类(启用动态高度)。
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