ios - AutoLayout Storyboard 约束 - 如何在代码中修改以在 Orientation 更改中使用此修改

标签 ios swift autolayout nslayoutconstraint

我考虑修改 Storyboard NSLayoutConstraint IBOutlets 值的最佳方式是什么,以使此修改保持方向/大小类更改。

我已经在 Storyboard 中定义了一些尺寸类别的已安装属性打开的约束,例如。 Regular/Compact,并关闭其他尺寸类别,如 Compact/Regular。

我可以通过 viewDidAppear() 中的 IBOutlet 从代码修改此约束的值,但它仅在我旋转设备之前有效。 卸载设备旋转约束后,再次使用旧 Storyboard值重新安装(或者如果在代码中停用,则再次重新激活)。

所以我尝试在 traitCollactionDidChange() 方法中添加额外的修改。但它不起作用,它在设置 Stroyboard 约束值之前被调用!所以我的修改被 Storyboard 中定义的值覆盖了。

然后我尝试了 viewDidLayoutSubviews() (UIViewController) 或 layoutSubviews() (UIView)。在简单 View 的情况下,它似乎可以工作,但如果我添加更多 View 修改然后计算将我的应用程序卡在旋转上,它就不可靠了。

因此,作为最后的手段,我将延迟 1 秒的 Timer.scheduledTimer() 添加到 traitCollectionDidChange() 中,它似乎有效,但它似乎也很奇怪。如果 Storyboard在这一秒后设置约束值,苹果可能会在下一版本的 Swift/iOS 中更改某些内容。我可以转发这样的 hack 吗?

我的代码:

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

        if UIDevice.current.userInterfaceIdiom == .pad  {
            bottomConstraint.isActive = false
        } else if traitCollection.sizeClasses == (.regular, .compact) {
            iphoneLeadingSpacerProportionalWidth = leadingSpacerProportionalWidth.setMultiplier(multiplier: 0.1)
            iphoneTrailingSpacerProportionaWidth = trailingSpacerProportionalWidth.setMultiplier(multiplier: 0.1)
        }
    }

    private var iphoneLeadingSpacerProportionalWidth : NSLayoutConstraint? = nil
    private var iphoneTrailingSpacerProportionaWidth : NSLayoutConstraint? = nil

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if let leadingConstraint = iphoneLeadingSpacerProportionalWidth,
            let trailingConstraint = iphoneTrailingSpacerProportionaWidth {
            NSLayoutConstraint.deactivate([leadingConstraint, trailingConstraint])
        }

        Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (timer) in
            if UIDevice.current.userInterfaceIdiom == .pad  {
                self.bottomConstraint.isActive = false
            } else if self.traitCollection.sizeClasses == (.regular, .compact) {
                self.iphoneLeadingSpacerProportionalWidth = self.leadingSpacerProportionalWidth.setMultiplier(multiplier: 0.1)
                self.iphoneTrailingSpacerProportionaWidth = self.trailingSpacerProportionalWidth.setMultiplier(multiplier: 0.1)
            }
        }
    }

重要!这个 setMultiplier() 使用了我发现的一些扩展,所以不要注意它,如果我设置 constraint.constant = toSomeValue

它的工作方式相同

最佳答案

您可以在 Storyboard 中为不同的大小类设置不同的值。见附件。

enter image description here

enter image description here

如果您仍想通过代码更新。您应该使用它来检测方向。

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}

关于ios - AutoLayout Storyboard 约束 - 如何在代码中修改以在 Orientation 更改中使用此修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52790050/

相关文章:

ios - 条件绑定(bind)的初始化程序必须具有 Optional 类型,而不是 '[AnyHashable : Any]'

ios - 如何在 xcode 6 中设置表格单元格颜色?

ios - UICollectionView 组合布局 - iPad 旋转时项目大小未正确更新

ios - Xcode 6 GM 种子无法启动 ios 模拟器

ios - 就像谷歌有操作系统版本/设备的官方统计数据一样,苹果有使用 ios5/4.x 的 % 设备的统计数据吗?

ios - 报亭应用

ios - uitablviewcell 动态高度与 systemLayoutSizeFittingSize 不正确

ios - Swift 圆形图像动画

ios - swift TableView deleteRowsAtIndexPaths NSException

ios - xCode 自动布局不适用于所有 iPhone 屏幕