【问题标题】:iOS - Issue with NSLayoutConstraint when rotating deviceiOS - 旋转设备时出现 NSLayoutConstraint 问题
【发布时间】:2021-08-27 16:51:51
【问题描述】:

我有一个 iOS 视图,它由一个带有 headerView 的 collectionView 组成。视图显示正常,但是当我旋转设备 (iPad) 时,标题元素会重复并且不正确。输出窗口显示如下

(
"<NSLayoutConstraint:0x600000051860 H:|-(0)-[UIImageView:0x7fe602031e40]   (active, names: '|':MYAPP.HeaderCollectionReusableView:0x7fe602031c40 )>",
"<NSLayoutConstraint:0x600000053a20 UIImageView:0x7fe602031e40.trailing == MYAPP.HeaderCollectionReusableView:0x7fe602031c40.trailing   (active)>",
"<NSLayoutConstraint:0x600000050be0 UIImageView:0x7fe602031e40.width == 1024   (active)>",
"<NSLayoutConstraint:0x6000000218b0 'UIView-Encapsulated-Layout-Width' MYAPP.HeaderCollectionReusableView:0x7fe602031c40.width == 1093   (active)>"
)

我知道问题出在 Header 中的 imageView 中,但不确定到底是什么。

这些是标题视图中图像的约束:

episodeImageView.anchor(top: topAnchor, leading: leadingAnchor, bottom: nil, trailing: trailingAnchor, size: .init(width: width, height: 0))
episodeImageView.heightAnchor.constraint(equalTo: episodeImageView.widthAnchor, multiplier: 0.65).isActive = true

我正在使用以下扩展进行锚定:

extension UIView {
var width: CGFloat {
    return frame.size.width
}

var height: CGFloat {
    return frame.size.height
}

var left: CGFloat {
    return frame.origin.x
}

var right: CGFloat {
    return left + width
}

var top: CGFloat {
    return frame.origin.y
}

var bottom: CGFloat {
    return top + height
}

func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
    
    translatesAutoresizingMaskIntoConstraints = false
    
    if let top = top {
        topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
    }
    
    if let leading = leading {
        leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
    }
    
    if let bottom = bottom {
        bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
    }
    
    if let trailing = trailing {
        trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
    }
    
    if size.width != 0 {
        widthAnchor.constraint(equalToConstant: size.width).isActive = true
    }
    
    if size.height != 0 {
        heightAnchor.constraint(equalToConstant: size.height).isActive = true
    }
}
}

这些是集合视图的约束:

private func setConstraints() {
    var devWidth: CGFloat = 0.0
    if UIDevice.current.orientation.isLandscape {
        devWidth = view.width * 0.8
    } else {
        devWidth = view.height * 0.8
    }
    
    leadingCVAnchor = collectionView?.leadingAnchor.constraint(equalTo: view.leadingAnchor)
    trailingCVAnchor = collectionView?.trailingAnchor.constraint(equalTo: view.trailingAnchor)
    centerCVAnchor = collectionView?.centerXAnchor.constraint(equalTo: view.centerXAnchor)
    widthCVAnchor = collectionView?.widthAnchor.constraint(equalToConstant: devWidth)
    
    collectionView?.translatesAutoresizingMaskIntoConstraints = false
    
    collectionView?.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    collectionView?.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    leadingCVAnchor?.isActive = true
    trailingCVAnchor?.isActive = true
    
    if UIDevice.current.userInterfaceIdiom == .pad {
        if UIDevice.current.orientation.isLandscape {
            centerCVAnchor?.isActive = true
            widthCVAnchor?.isActive = true
            leadingCVAnchor?.isActive = false
            trailingCVAnchor?.isActive = false
        } else {
            leadingCVAnchor?.isActive = true
            trailingCVAnchor?.isActive = true
        }
    } else {
        leadingCVAnchor?.isActive = true
        trailingCVAnchor?.isActive = true
    }
}

使用此覆盖到 viewWillTransition:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.userInterfaceIdiom == .pad {
        if UIDevice.current.orientation.isLandscape {
            print("Orientation Landscape")
            leadingCVAnchor?.isActive = false
            trailingCVAnchor?.isActive = false
            widthCVAnchor?.isActive = true
            centerCVAnchor?.isActive = true
        } else {
            print("Orientation Portrait")
            leadingCVAnchor?.isActive = true
            trailingCVAnchor?.isActive = true
            widthCVAnchor?.isActive = false
            centerCVAnchor?.isActive = false
        }
    }
}

这个项目不使用故事板,一切都是用代码完成的。

我对约束还很陌生,所以不确定在哪里解决问题或如何解释 NSLayoutConstraint 警告。

我该如何解决这个约束问题?

【问题讨论】:

    标签: ios autolayout nslayoutconstraint


    【解决方案1】:

    问题是 1024 和 1093 不是同一个数字。您已经限制宽度,使其必须为 1024。您还说前缘应该固定到其他视图,后缘也固定到其他视图,这些东西相距 1093。不能两者兼得。

    【讨论】:

    • 谢谢。考虑到这一点,我发现了错误,并且我不再收到错误了。但是,标题元素仍在重复。我相信这完全是由其他原因引起的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多