我有五个使用autolayout约束的UIView实例.在纵向模式下,它们适合屏幕,但在横向模式下,屏幕变小,可以容纳所有视图.

我知道一种解决方法,即创建两个约束,在纵向模式下激活一个约束,在横向模式下禁用另一个约束,反之亦然,如下所示:

class ViewController : UIViewController{
  var portraitHeight : NSLayoutConstraint!
  var landscapeHeight : NSLayoutConstraint!

  viewDidLoad(){
    super.viewDidLoad()
    portraitHeight = firstView.heightAnchor.constraint(equalToConstant: 88)
    landscapeHeight = firstView.heightAnchor.constraint(equalToConstant: 68)
  }

 override func viewWillLayoutSubviews() {
    let orientation = UIDevice.current.orientation
    if orientation == .portrait
    {
        landscapeHeight.isActive = false
        portraitHeight.isActive = true
        
    }else if orientation == .landscapeLeft || orientation == .landscapeRight
    {
        portraitHeight.isActive = false
        landscapeHeight.isActive = true
       
    }
  }
}

但我真正想要的是,当没有足够的空间时,能够挤压视图.

以下是我的限制:

NSLayoutConstraint.activate([
        firstView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        firstView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor),
        firstView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor),
        firstView.heightAnchor.constraint(equalToConstant: 88),
        
        secondView.topAnchor.constraint(equalTo: firstView.bottomAnchor),
        secondView.leftAnchor.constraint(equalTo: firstView.leftAnchor),
        secondView.rightAnchor.constraint(equalTo: firstView.rightAnchor),
        secondView.heightAnchor.constraint(equalTo: firstView.heightAnchor),
        
        thirdView.topAnchor.constraint(equalTo: secondView.bottomAnchor),
        thirdView.leftAnchor.constraint(equalTo: firstView.leftAnchor),
        thirdView.rightAnchor.constraint(equalTo: firstView.rightAnchor),
        thirdView.heightAnchor.constraint(equalTo: firstView.heightAnchor),
        
        fourthView.topAnchor.constraint(equalTo: thirdView.bottomAnchor),
        fourthView.leftAnchor.constraint(equalTo: firstView.leftAnchor),
        fourthView.rightAnchor.constraint(equalTo: firstView.rightAnchor),
        fourthView.heightAnchor.constraint(equalTo: firstView.heightAnchor),
        
        fifthView.topAnchor.constraint(equalTo: fourthView.bottomAnchor),
        fifthView.leftAnchor.constraint(equalTo: firstView.leftAnchor),
        fifthView.rightAnchor.constraint(equalTo: firstView.rightAnchor),
        fifthView.heightAnchor.constraint(equalTo: firstView.heightAnchor),

    ])

所需输出:

enter image description here

enter image description here

推荐答案

我们可以向第一个视图添加多个高度约束,只要它们不冲突.

所以,我们想告诉第一个视图100的高度为88点.我们将为该约束提供一个低于所需优先级的优先级,以便自动布局可以在必要时打破它:

let firstHeight: NSLayoutConstraint = firstView.heightAnchor.constraint(equalToConstant: 88.0)
firstHeight.priority = .required - 1

我们不希望其ever小于88点,因此我们将为其提供第二个小于或等于88的所需高度约束:

firstView.heightAnchor.constraint(lessThanOrEqualToConstant: 88.0)

并且,为了防止第五个视图超出安全区域底部,我们将给它一个小于或等于的约束:

fifthView.bottomAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.bottomAnchor)

下面是一个完整的示例:

class FiveViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let firstView = UIView()
        firstView.backgroundColor = .red
        let secondView = UIView()
        secondView.backgroundColor = .cyan
        let thirdView = UIView()
        thirdView.backgroundColor = .yellow
        let fourthView = UIView()
        fourthView.backgroundColor = .green
        let fifthView = UIView()
        fifthView.backgroundColor = .orange

        [firstView, secondView, thirdView, fourthView, fifthView].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(v)
        }

        // we want the first view to TRY to be 88-points tall
        let firstHeight: NSLayoutConstraint = firstView.heightAnchor.constraint(equalToConstant: 88.0)
        // but with less-than-required priority so it can shrink
        firstHeight.priority = .required - 1
        
        
        NSLayoutConstraint.activate([
            
            firstView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            firstView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor),
            firstView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor),

            // don't do this
            //firstView.heightAnchor.constraint(equalToConstant: 88),

            firstHeight,
            
            // we don't want the view heights to be Greater-Than 88-points
            firstView.heightAnchor.constraint(lessThanOrEqualToConstant: 88.0),

            secondView.topAnchor.constraint(equalTo: firstView.bottomAnchor),
            secondView.leftAnchor.constraint(equalTo: firstView.leftAnchor),
            secondView.rightAnchor.constraint(equalTo: firstView.rightAnchor),
            secondView.heightAnchor.constraint(equalTo: firstView.heightAnchor),
            
            thirdView.topAnchor.constraint(equalTo: secondView.bottomAnchor),
            thirdView.leftAnchor.constraint(equalTo: firstView.leftAnchor),
            thirdView.rightAnchor.constraint(equalTo: firstView.rightAnchor),
            thirdView.heightAnchor.constraint(equalTo: firstView.heightAnchor),
            
            fourthView.topAnchor.constraint(equalTo: thirdView.bottomAnchor),
            fourthView.leftAnchor.constraint(equalTo: firstView.leftAnchor),
            fourthView.rightAnchor.constraint(equalTo: firstView.rightAnchor),
            fourthView.heightAnchor.constraint(equalTo: firstView.heightAnchor),
            
            fifthView.topAnchor.constraint(equalTo: fourthView.bottomAnchor),
            fifthView.leftAnchor.constraint(equalTo: firstView.leftAnchor),
            fifthView.rightAnchor.constraint(equalTo: firstView.rightAnchor),
            fifthView.heightAnchor.constraint(equalTo: firstView.heightAnchor),
            
            // we want the fifth view Bottom to never extend below the safe area Bottom
            fifthView.bottomAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.bottomAnchor),
            
        ])
    }
}

结果是:

enter image description here

enter image description here

Swift相关问答推荐

Swift concurrency reload/await,支持只执行成功并重试

如何禁用MacOS上SwiftUI中按钮周围的聚焦环(或高亮显示)?

Swift-Can无法在AudioKit中找出简单的麦克风效果-文件链

为SwiftUI文本视图提供固定宽度,并仅在文本换行时使文本视图底部增大

可以';t在标记为@Observable的类上使用属性包装

Swift ui 转换无法按预期工作

更改 SwiftUI 中按钮矩阵的填充 colored颜色

在SwiftUI中使用ForEach循环来显示字典项的键和值在Form视图中

UIBezierPath() 和 DragGesture:连接点创建角而不是曲线

允许为 self 分配新的 struct 值的理由是什么?

自定义碰撞形状出现在错误的位置

如何自己实现同一个 iOS 16 锁屏圆形小部件?

如何避免从模块导入函数

RxSwift 提高性能

Swift:创建用于调用 C 函数的指针数组

找不到接受提供的参数的/的重载

Swift 5.0 编译器无法导入使用 Swift 4.2.1 编译的模块

为什么 swift 中的类没有存储类型属性?

如何更改弹出框的大小

使用 JSONEncoder 对类型为 Codable 的变量进行编码