让UIView垂直拉伸到一定的边距

问题描述 投票:0回答:1

我有一个

UIView
,内容可能会垂直溢出,我设置了一个垂直约束(高度约束,但顶部/底部约束具有相同的效果)以防止整个视图(弹出窗口)溢出。

我的目标是让视图占据其内容所需的高度,直到它从屏幕边缘(安全区域)进入预先配置的顶部和底部边距。

我的问题是,一旦我将设备旋转到横向并返回到纵向,弹出窗口就不会像垂直方向那样拉伸。

我已经尝试过的事情:

  1. 高度优先考虑高度限制。
  2. itemView
    上设置高抗压性。
  3. 更新约束后调用
    layoutIfNeeded
  4. 创建另一个优先级较低的高度约束,告诉视图全程拉伸。

显然这些都不起作用。

初始状态:

旋转后:

旋转回纵向:

代码如下所示:

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()
    }
ios swift uiview uikit constraints
1个回答
0
投票

您的模态呈现视图本质上受到限制。我回答了一些类似的问题here。由于受到约束,布局引擎在初始加载期间以一种方式解决布局,然后当您返回到纵向模式时以另一种方式解决布局。当视图受到约束或以其他方式模糊时,就会发生这种情况。

如果你适当地约束你的观点,那么你就不会有这个问题。我复制了你的观点。请参阅以下结果:

完整解决方案真的很长,所以我只会发布最相关的部分。

  1. 我首先创建一个带有圆角和白色背景的 UIView。我称之为容器视图。我将此容器视图作为唯一的子视图添加到视图控制器的视图中。
  2. 然后这个容器视图也有一个子视图:UIStackView,周围有一些填充。
  3. 然后我将其他所有内容嵌入到此 StackView 中。在这个例子中,我从上到下有 UILabel、UITexView、UIButton、UIButton、UIButton。
  4. 确保 StackView 中的标题标签 (RITM0010007) 具有固定的高度。在我的示例中,我将此高度定义为 45 点。
  5. 如果您使用 UITextView 作为主要内容,请确保它不可滚动。您可以使用 UITextView 或 UILabel 作为主要内容。不要对此定义任何限制。
  6. 确保堆栈视图中的按钮也定义了高度。我的分数是 36 分。
  7. 确保 Stackview 的对齐方式是填充的。
  8. Stackview 负责处理其余缺失的约束。

这就是代码中创建容器视图的方式:

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)
    ])
}
© www.soinside.com 2019 - 2024. All rights reserved.