以编程方式为不同大小类创建具有不同常量的自动布局约束

Posted

技术标签:

【中文标题】以编程方式为不同大小类创建具有不同常量的自动布局约束【英文标题】:Programmatically create auto layout constraints with different constants for different size classes 【发布时间】:2015-07-11 22:30:30 【问题描述】:

如果您使用 Storyboard,您可以使用 Interface Builder 向视图添加自动布局约束,并且您可以非常轻松地为所需的每个大小类别添加不同的 constant 值。当您运行应用并在尺寸类别之间切换时,UI 将自动更新并重新定位以尊重新尺寸类别的正确 constant 值。

我的问题是如何以编程方式获得相同的行为?

当您创建NSLayoutConstraint 时,您不能为不同的尺寸等级设置不同的值。因此,我认为这将是一个更加手动的过程。例如,您必须在 viewDidLoad 中为当前尺寸类创建具有正确值的约束,然后您必须使用 willTransitionToTraitCollectionupdateConstraints 并检测新的尺寸类,然后更改 @ 987654327@s 适用于新尺寸类的所有约束,然后在需要重新定位的视图上调用 layoutIfNeeded。那将是很多代码,您优化的大小类越多,情况就越糟。难道没有更简单和/或更有效的方式来以编程方式获取该行为吗?

请注意,此问题不仅限于自动布局约束,而是任何可以根据大小类更改其属性值的对象。例如,为不同的大小等级设置UILabel的字体。

【问题讨论】:

我没有找到干净的解决方案。必须在 viewDidLoad 中以及在检测到大小类更改之后进行优化。 @SwiftArchitect 可惜苹果没有提供addConstraint:forSizeClasses或者activateConstraints:forSizeClasses... @SwiftArchitect 现在提交雷达 :) 【参考方案1】:

斯威夫特

你需要创建不同的NSLayoutConstraint集合。

根据下面的讨论进行编辑。

@Joey:您必须在viewDidLoad(或类似的)和viewWillTransitionToSize 中处理大小等级决定。

大小类检测应该在animateAlongsideTransition 块内完成,而不是之前。

重构代码:

override func viewDidLoad() 
    super.viewDidLoad()
    let narrow = self.view.traitCollection.horizontalSizeClass 
                 == UIUserInterfaceSizeClass.Compact
    self.useNarrowConstraints(narrow)



override func viewWillTransitionToSize(size: CGSize,
                                       withTransitionCoordinator
                                       coordinator: UIViewControllerTransitionCoordinator) 
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    coordinator.animateAlongsideTransition(
        (UIViewControllerTransitionCoordinatorContext) -> Void in
            let narrow = self.view.traitCollection.horizontalSizeClass 
                         == UIUserInterfaceSizeClass.Compact
            self.useNarrowConstraints(narrow)
        )
         (UIViewControllerTransitionCoordinatorContext) -> Void in 
        

使用激活:

func useNarrowConstraints(narrow: Bool) 
    if narrow 
        NSLayoutConstraint.deactivateConstraints([self.fullWidthConstraint])
        NSLayoutConstraint.activateConstraints([self.halfWidthConstraint])
     else 
        NSLayoutConstraint.deactivateConstraints([self.halfWidthConstraint])
        NSLayoutConstraint.activateConstraints([self.fullWidthConstraint])
    

更多详情here。

使用替换:

func useNarrowConstraints(narrow: Bool) 
    view.removeConstraint(constraint)
    
    if narrow 
        constraint = NSLayoutConstraint.constraintsWithVisualFormat("format", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
     else 
        constraint = NSLayoutConstraint.constraintsWithVisualFormat("otherFormat", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
    
    view.addConstraint(constraint)

【讨论】:

这段代码会去哪里?每次大小类更改时,您肯定必须删除所有约束并使用正确的常量重新添加它们。 请注意,加载视图时不会调用此方法。您需要在“viewDidLoad”中复制该代码。不像我想要的那样干净,删除约束并读取它们的效率也非常低,但它会起作用。 两个帐户都正确。效率是一个感知问题;更好地选择一个好的算法,而不是优化一个糟糕的算法。因此,我的建议是尽可能选择 Storyboard 而不是编程解决方案。 你不能打败 0 行代码,让操作系统来做艰苦的工作。

以上是关于以编程方式为不同大小类创建具有不同常量的自动布局约束的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式设置 AutoLayout 大小类?

以编程方式创建 UITableViewCells

预览具有不同大小和语言样式的自动布局

具有自动布局约束的 UITableViewCell 子类大小不正确

基于在 Storyboard 中使用自动布局创建的另一个视图,以编程方式使用框架创建视图

如何以编程方式更改使用自动布局在情节提要上创建的 UIImageView 的大小?