我有一个
UIView
,内容可能会垂直溢出,我设置了一个垂直约束(高度约束,但顶部/底部约束具有相同的效果)以防止整个视图(弹出窗口)溢出。
我的目标是让视图占据其内容所需的高度,直到它从屏幕边缘(安全区域)进入预先配置的顶部和底部边距。
我的问题是,一旦我将设备旋转到横向并返回到纵向,弹出窗口就不会像垂直方向那样拉伸。
我已经尝试过的事情:
itemView
上设置高抗压性。layoutIfNeeded
。显然这些都不起作用。
初始状态:
旋转后:
旋转回纵向:
代码如下所示:
class PopupView: UIView, SpinnerProvider {
lazy var spinner: SNSpinnerView = {
let spinner = SNSpinnerView()
spinner.translatesAutoresizingMaskIntoConstraints = false
spinner.spinnerImageView.image = spinnerImageDefault
spinner.isHidden = false
return spinner
}()
var itemView = UIView() {
didSet {
spinner.isHidden = true
UIView.animate(withDuration: Constants.animationDuration) {
self.backgroundColor = .snDarkDimming
}
popupContainerView.addChild(itemView)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
private lazy var popupContainerView: UIView = {
let view = UIView(frame: .zero)
view.layer.cornerRadius = Constants.popUpFrameCornerRadius
view.layer.masksToBounds = true
view.accessibilityIdentifier = "popup"
return view
}()
private lazy var containerHeightConstraint: NSLayoutConstraint = {
// Constant will change.
popupContainerView.heightAnchor.constraint(lessThanOrEqualToConstant: 0)
}()
private lazy var containerLeadingConstraint: NSLayoutConstraint = {
popupContainerView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor)
}()
private lazy var containerTrailingConstraint: NSLayoutConstraint = {
popupContainerView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor)
}()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
backgroundColor = .snLoadingViewBackground
useAutoLayout()
addSubview(popupContainerView)
popupContainerView.useAutoLayout()
.center(in: self)
addSubview(spinner)
spinner.useAutoLayout()
.center(in: self)
spinner.startRotationAnimation()
NSLayoutConstraint.activate([
containerHeightConstraint,
containerLeadingConstraint,
containerTrailingConstraint
])
adjustConstraints()
}
func adjustConstraints() {
if UIDevice.current.orientation.isPortrait {
containerLeadingConstraint.constant = Constants.Portrait.leadingInset
containerTrailingConstraint.constant = Constants.Portrait.trailingInset
containerHeightConstraint.constant = UIScreen.main.bounds.height - safeAreaLayoutGuide.layoutFrame.height - (Constants.Portrait.horizontalInset * 2)
} else {
containerLeadingConstraint.constant = Constants.Landscape.leadingInset
containerTrailingConstraint.constant = Constants.Landscape.trailingInset
containerHeightConstraint.constant = UIScreen.main.bounds.height - (Constants.Landscape.horizontalInset * 2)
}
}
}
adjustConstraints
从父视图调用:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
popupView.adjustConstraints()
}
您的模态呈现视图本质上受到限制。我回答了一些类似的问题here。由于受到约束,布局引擎在初始加载期间以一种方式解决布局,然后当您返回到纵向模式时以另一种方式解决布局。当视图受到约束或以其他方式模糊时,就会发生这种情况。
如果你适当地约束你的观点,那么你就不会有这个问题。我复制了你的观点。请参阅以下结果:
完整解决方案真的很长,所以我只会发布最相关的部分。
这就是代码中创建容器视图的方式:
private func configureContainerView() {
//containerView is declared at the view controller level
containerView = UIView()
containerView.backgroundColor = .systemBackground
containerView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMinXMinYCorner, .layerMaxXMaxYCorner, .layerMaxXMinYCorner]
containerView.layer.cornerRadius = 12
containerView.layer.borderColor = UIColor.black.cgColor
containerView.layer.borderWidth = 1
containerView.clipsToBounds = true
containerView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(containerView)
NSLayoutConstraint.activate([
containerView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor, constant: 20),
containerView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -20),
containerView.topAnchor.constraint(greaterThanOrEqualTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 20),
containerView.bottomAnchor.constraint(lessThanOrEqualTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: -20),
containerView.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor)
])
}
这就是代码中创建堆栈视图的方式:
private func configureStackView() {
//primaryStackView is declared at the view controller level
primaryStackView = UIStackView()
primaryStackView.axis = .vertical
primaryStackView.spacing = 16
primaryStackView.alignment = .fill
primaryStackView.translatesAutoresizingMaskIntoConstraints = false
self.containerView.addSubview(primaryStackView)
NSLayoutConstraint.activate([
primaryStackView.leadingAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.leadingAnchor, constant: 20),
primaryStackView.trailingAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.trailingAnchor, constant: -20),
primaryStackView.topAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.topAnchor, constant: 20),
primaryStackView.bottomAnchor.constraint(equalTo: containerView.safeAreaLayoutGuide.bottomAnchor, constant: -20)
])
}
确保其余内容已添加到堆栈视图中,如下所示:
private func configureTitleView() {
let titleLabel = UILabel()
//configure title label
primaryStackView.addArrangedSubview(titleLabel)
NSLayoutConstraint.activate([
titleLabel.heightAnchor.constraint(equalToConstant: 45)
])
}