【问题标题】:How to deal with safe area when using Size Classes?使用 Size Classes 时如何处理安全区域?
【发布时间】:2019-10-27 03:04:45
【问题描述】:

我刚刚创建了一个简单的红色视图并为其创建了 4 个约束(上、左、右、下)。我正在尝试使用尺寸类进行自适应布局,但无法在“横向”方向实现正确布局:

  1. 在纵向模式下一切正常。下、左、右边缘到超级视图的边缘,上边缘到安全区域的顶部。
  2. 在横向左侧模式下一切正常。顶部、右侧边缘到超级视图的边缘,左侧和底部到安全区域的边缘。
  3. 但在横向模式下布局不正确。我希望,左边缘将等于 superview 的左边缘,但实际上它等于安全区域。右边缘也一样:我希望它等于安全区域的边缘,但实际上它等于超级视图的边缘。如何修复

【问题讨论】:

  • 请提供这些:您所做设置的图像。结果的图像。您想要的图像。

标签: ios xcode autolayout size-classes adaptive-layout


【解决方案1】:

首先为尺寸类创建单独的常量仅用于顶部约束。看看我的图片。然后为前导和尾随约束创建一个出口。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var conTrailing: NSLayoutConstraint!
    @IBOutlet weak var conLeading: NSLayoutConstraint!     

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.setOrientationAllignment()
    }

    func setOrientationAllignment() {
        switch UIDevice.current.orientation {
        case .portrait:
            self.conLeading.constant = 0
            self.conTrailing.constant = 0
        case .landscapeLeft:
            self.conLeading.constant = 40
            self.conTrailing.constant = 0
        case .landscapeRight:
            self.conLeading.constant = 00
            self.conTrailing.constant = 40
        default:
            break
        }
        self.view.layoutSubviews() //  no  need  now
        self.view.layoutIfNeeded()
    }        

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)        
        self.setOrientationAllignment()
    }
}

【讨论】:

  • 代码中的约束可以是一些鸭带,这是有道理的。我认为通过 Interface Builder 有一些自动方法可以做到这一点
【解决方案2】:

据我了解,您要实现的是每当手机处于横向位置时,您的红色视图的边缘应该等于手机底部一侧的超级视图的相应边缘。如果是这样,您可以创建 4 个约束,2 个用于右侧,2 个用于左侧。

让我们考虑红色视图前沿的两个约束: 1)红色视图的前沿等于superview的前沿 2)红色视图的前沿等于SafeArea

所有约束的默认优先级为 999

然后,您可以在视图控制器中执行以下操作:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    let lowPriority = UILayoutPriority(rawValue: 250)
    let highPriority = UILayoutPriority(rawValue: 999)

    switch UIDevice.current.orientation {
    case .landscapeLeft:
        leftEdgeToSafeAreaConstraint.priority = highPriority
        rightEdgeToSafeAreaConstraint.priority = lowPriority

        leftEdgeToSuperviewConstraint.priority = lowPriority
        rightEdgeToSuperviewConstraint.priority = highPriority
    case .landscapeRight:
        leftEdgeToSafeAreaConstraint.priority = lowPriority
        rightEdgeToSafeAreaConstraint.priority = highPriority

        leftEdgeToSuperviewConstraint.priority = highPriority
        rightEdgeToSuperviewConstraint.priority = lowPriority
    default:
        leftEdgeToSafeAreaConstraint.priority = highPriority
        rightEdgeToSafeAreaConstraint.priority = highPriority

        leftEdgeToSuperviewConstraint.priority = lowPriority
        rightEdgeToSuperviewConstraint.priority = lowPriority
    }
}

【讨论】:

  • 代码中的约束可以是一些鸭带,这是有道理的。我认为通过 Interface Builder 有一些自动方法可以做到这一点
【解决方案3】:

我正在努力使用 left、right、top、bottom 锚点进行设备旋转。

对于右侧景观,您应该对顶部边缘和状态栏保持安静。

如果您正确理解视图层次结构,您可以使用如下代码示例:

        let deleteButtonImage = UIImage(named: "DeleteButton") as UIImage?  
        let deleteButtonImageSize: CGSize = CGSize(width: 295, height: 45)
        let deleteButton = UIButton(type: UIButton.ButtonType.custom)
        deleteButton.translatesAutoresizingMaskIntoConstraints = false
        deleteButton.tintColor = .white
        deleteButton.frame = CGRect(x: 0, y: 0, width: 250, height: 135)
        deleteButton.setImage(deleteButtonImage, for: .normal)

        deleteButton.imageEdgeInsets = UIEdgeInsets(
            top: (deleteButton.frame.size.height - deleteButtonImageSize.height) / 2,
            left: (deleteButton.frame.size.width - deleteButtonImageSize.width) / 2.5,
            bottom: (deleteButton.frame.size.height - deleteButtonImageSize.height) / 2,
            right: (deleteButton.frame.size.width - deleteButtonImageSize.width) / 2.5)


        scrollView.addSubview(deleteButton)

        deleteButton.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        deleteButton.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: -150).isActive = true
        deleteButton.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 370).isActive = true
        deleteButton.widthAnchor.constraint(equalTo: self.scrollView.safeAreaLayoutGuide.widthAnchor).isActive = true
        deleteButton.heightAnchor.constraint(equalToConstant: 45).isActive = true

   }

【讨论】:

  • 代码中的约束可以是一些鸭带,这是有道理的。我认为通过 Interface Builder 有一些自动方法可以做到这一点
【解决方案4】:

将顶部、左侧、右侧边距设置为 0 以对齐 安全区域。 并使用 Superview 从底部到 0。

【讨论】:

    猜你喜欢
    • 2020-08-13
    • 2021-01-30
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多