代码之家  ›  专栏  ›  技术社区  ›  Ashley Mills

子类化UICollectionViewFlowLayout-在iOS 12中自动调整单元格帧计算问题

  •  2
  • Ashley Mills  · 技术社区  · 6 年前

    我用下面的方法在 UICollectionView

    class LeftAlignedFlowLayout: UICollectionViewFlowLayout {
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil }
    
            for attributes in attributes where attributes.representedElementCategory == .cell {
                attributes.frame = layoutAttributesForItem(at: attributes.indexPath).frame
            }
            return attributes
        }
    
        override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes {
            let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)!
    
            let layoutWidth = collectionView!.frame.width - sectionInset.left - sectionInset.right
    
            // Just left align the first item in a section
            if indexPath.item == 0 {
                currentItemAttributes.frame.origin.x = sectionInset.left
                return currentItemAttributes
            }
    
            let previousIndexPath = IndexPath(item: indexPath.item - 1, section: indexPath.section)
            let previousItemFrame = layoutAttributesForItem(at: previousIndexPath).frame
    
            let currentItemFrame = currentItemAttributes.frame
            let wholeRowFrameForCurrentItem = CGRect(x: sectionInset.left, y: currentItemFrame.minY, width: layoutWidth, height: currentItemFrame.height)
    
            // Left align the first item on a row
            if !previousItemFrame.intersects(wholeRowFrameForCurrentItem) {
                currentItemAttributes.frame.origin.x = sectionInset.left
                return currentItemAttributes
            }
    
            currentItemAttributes.frame.origin.x = previousItemFrame.maxX + minimumInteritemSpacing
            return currentItemAttributes, it's 
        }
    }
    

    为iOS 11构建

    enter image description here

    enter image description here

    在iOS 11中, layoutAttributesForElements(in) 称为3次-最后一次使用正确的帧大小。在iOS 12中,它只调用两次,帧是估计的大小。

    根据这个答案, https://stackoverflow.com/a/52148520/123632 我尝试使用 ui集合视图 viewDidAppear 但结果不变。

    class LeftAlignedCollectionView: UICollectionView {
    
        private var shouldInvalidateLayout = false
    
        override func layoutSubviews() {
            super.layoutSubviews()
            if shouldInvalidateLayout {
                collectionViewLayout.invalidateLayout()
                shouldInvalidateLayout = false
            }
        }
    
        override func reloadData() {
            shouldInvalidateLayout = true
            super.reloadData()
        }
    }
    
    3 回复  |  直到 6 年前
        1
  •  2
  •   ahbou    6 年前

    这是iOS 12中的已知问题(请参阅此处的UIKit部分: https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes

    解决办法是要么不打电话 setNeedsUpdateConstraints() updateConstraintsIfNeeded() 打电话之前 systemLayoutSizeFitting(_:) .

        2
  •  1
  •   Ashley Mills    6 年前

    contentView 给牢房修好了

    override func awakeFromNib() {
        contentView.translatesAutoresizingMaskIntoConstraints = false
    
        NSLayoutConstraint.activate([contentView.leftAnchor.constraint(equalTo: leftAnchor),
                                     contentView.rightAnchor.constraint(equalTo: rightAnchor),
                                     contentView.topAnchor.constraint(equalTo: topAnchor),
                                     contentView.bottomAnchor.constraint(equalTo: bottomAnchor)])
    }
    
        3
  •  0
  •   EnasAZ    6 年前

    我在MyCustomCollectionViewCell文件中添加了这个,它运行良好

    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
    
        return contentView.systemLayoutSizeFitting(CGSize(width: targetSize.width, height: 1))
    }