Swift-自计算约束布局

前言

  随着硬件性能的不断提升,以往为了减少设备性能的消耗而进行预计算视图高度正逐步被xib约束布局替换,举个例子,我们可以直接在xib中设置好各视图控件的相对约束位置,之后根据具体的宽度来计算对应的高度,该方法能有效的降低手动计算产生误差的情况。
  当然也不能完全不考虑性能问题,针对计算出来的高度需要进行缓存,减少同一视图的重复计算。

UICollectionView中的使用

布局设置

  设置子视图与Collection View Cell容器的相对位置。

  由于高度需要通过子视图来计算,所以我给子视图设置了一个固定高度 128,且设置好上下间距 8,这样根据自动布局的计算,最后得到的高度就是 128+8+8=144,但是这个高度与当前contentView的高度 200 不符合,引起了冲突。
  为了消除这个冲突但又不影响高度的计算,我们有两个方法来解决,下面我们来看看具体是如何操作的。

方案一
  修改子视图底部间距优先值,默认优先值为1000,适当调低优先值,这个时候会变成一条虚线,冲突解除,并且不会影响后续的计算。


方案二
  调整Collection View Cell容器的高度与设置的高度相同,但是这个方案会导致每次布局轻微的调整就引起冲突,所以不推荐使用该方案

  至此就可以实现自动布局了

注意事项

Q1: 在部分iOS版本中会出现无论怎么调用 UIViewsystemLayoutSizeFitting方法返回的结果都是初始设置的值?
  这是因为UICollectionViewCell中的contentView视图约束并没有设定好,这个时候我们只需要对其设置约束即可。

open func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) - > CGSize

class Cell: UICollectionViewCell {

    override init(frame: CGRect) {
        super.init(frame: frame)
        contentView.translatesAutoresizingMaskIntoConstraints = false
        [contentView.topAnchor.constraint(equalTo: topAnchor),
         contentView.leftAnchor.constraint(equalTo: leftAnchor),
         contentView.rightAnchor.constraint(equalTo: rightAnchor),
         contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ].forEach({ $0.isActive = true })
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        contentView.translatesAutoresizingMaskIntoConstraints = false
        [contentView.topAnchor.constraint(equalTo: topAnchor),
         contentView.leftAnchor.constraint(equalTo: leftAnchor),
         contentView.rightAnchor.constraint(equalTo: rightAnchor),
         contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ].forEach({ $0.isActive = true })
    }
}

Q2: 当快速滑动时出现布局抖动的问题?
  由于初始情况并不明确到底cell有多大,这时候当实际计算结果偏差过大时就会出现这种抖动情况,我们可以给UICollectionViewFlowLayout添加一个预估值estimatedItemSize以减少抖动的情况,注意如果约束布局没有确定宽或高,则会直接沿用estimatedItemSize中设置的值。

func setupCollection() {
    let layout = UICollectionViewFlowLayout()
    layout.estimatedItemSize = CGSize(width: 100, height: 100)
    collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容