在UICollectionViewCell中使用TVPosterView引发异常尺寸问题
tvOS UICollectionView聚焦后Cell尺寸异常问题
问题现象
- 应用启动时:首个聚焦项(Camera A)尺寸大于其他项,所有Cell显示正常
- 切换聚焦项后:原聚焦项(Camera A)尺寸大幅缩小,当前聚焦项也不再有启动时的放大效果
相关代码
UICollectionViewDelegateFlowLayout实现
extension ListingViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let thumbWidth = CGFloat(320) let thumbHeight = CGFloat(thumbWidth * 0.7) return CGSize(width: thumbWidth, height: thumbHeight) } }
UICollectionViewCell核心代码
internal func setupUI() { posterView = TVPosterView() posterView.tag = 1100 posterView.clipsToBounds = false addSubview(posterView) posterView.alignToSuperView() }
UIView扩展方法alignToSuperView
public func alignToSuperView() { self.translatesAutoresizingMaskIntoConstraints = false guard let margins = self.superview?.layoutMarginsGuide else { return } self.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true self.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true self.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true self.bottomAnchor.constraint(equalTo: margins.bottomAnchor).isActive = true self.superview?.layoutIfNeeded() }
解决方案
1. 修正子视图约束逻辑
问题根源之一是使用layoutMarginsGuide作为约束参照,tvOS中Cell聚焦时会调整layoutMargins,导致子视图尺寸异常。修改alignToSuperView方法,直接对齐父视图边缘:
public func alignToSuperView() { self.translatesAutoresizingMaskIntoConstraints = false guard let superView = self.superview else { return } NSLayoutConstraint.activate([ leadingAnchor.constraint(equalTo: superView.leadingAnchor), trailingAnchor.constraint(equalTo: superView.trailingAnchor), topAnchor.constraint(equalTo: superView.topAnchor), bottomAnchor.constraint(equalTo: superView.bottomAnchor) ]) }
2. 配置UICollectionViewFlowLayout聚焦参数
显式设置FlowLayout的聚焦缩放比例,确保系统自动处理聚焦时的尺寸变化,避免手动修改ItemSize导致冲突:
// 在初始化UICollectionView时配置 let flowLayout = UICollectionViewFlowLayout() flowLayout.itemSize = CGSize(width: 320, height: 224) // 320*0.7 flowLayout.minimumInteritemSpacing = 20 flowLayout.minimumLineSpacing = 20 flowLayout.focusedItemScale = 1.2 // 聚焦时的缩放比例,默认1.2 flowLayout.sectionInset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) collectionView.collectionViewLayout = flowLayout
3. 避免冲突的聚焦逻辑
如果TVPosterView自带聚焦缩放效果,可能和UICollectionView的系统缩放冲突,禁用TVPosterView的自动聚焦调整:
posterView.adjustsImageWhenAncestorFocused = false
4. 移除过早的布局强制刷新
删除alignToSuperView中的self.superview?.layoutIfNeeded(),避免在约束激活阶段强制刷新导致布局计算错误。
内容的提问来源于stack exchange,提问作者Santanu Karar
相关产品推荐
相关产品推荐

