在设备轮换中保持自动布局约束活动状态

时间:2016-02-01 12:50:17

标签: ios autolayout

我注意到当我以编程方式更新自动布局约束时,在旋转屏幕时会恢复所有更改。

重现问题:

  • 基本故事板界面与UIView和2个约束:

    1. width等于superview.width(乘数1)有效
    2. 宽度等于superview.width(乘数1/2)已禁用
  • 使用IBOutlet

  • 创建并链接这两个约束
  • 以编程方式禁用第一个约束并启用第二个约束。
  • 旋转设备,第一个约束处于活动状态,第二个约束禁用。

对我来说似乎是个错误。

您怎么看?

截图:

故事板: enter image description here

约束#1:

enter image description here

约束#2:

enter image description here

3 个答案:

答案 0 :(得分:7)

大小类

已安装是指尺寸类安装,而不是有效 / 无效

您必须以编程方式创建另一个约束,并激活/停用那个。这是因为您无法更改约束的乘数(Can i change multiplier property for NSLayoutConstraint?),也无法修改大小类(activateConstraints: and deactivateConstraints: not persisting after rotation for constraints created in IB)。

有几种方法可以做到这一点。在下面的示例中,我使用乘数或 1/2 创建 x1 约束的副本。然后我在两者之间切换:

@IBOutlet var fullWidthConstraint: NSLayoutConstraint!
var halfWidthConstraint: NSLayoutConstraint!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    halfWidthConstraint = NSLayoutConstraint(item: fullWidthConstraint.firstItem,
        attribute: fullWidthConstraint.firstAttribute,
        relatedBy: fullWidthConstraint.relation,
        toItem: fullWidthConstraint.secondItem,
        attribute: fullWidthConstraint.secondAttribute,
        multiplier: 0.5,
        constant: fullWidthConstraint.constant)
    halfWidthConstraint.priority = fullWidthConstraint.priority
}

@IBAction func changeConstraintAction(sender: UISwitch) {
    if sender.on {
        NSLayoutConstraint.deactivateConstraints([fullWidthConstraint])
        NSLayoutConstraint.activateConstraints([halfWidthConstraint])
    } else {
        NSLayoutConstraint.deactivateConstraints([halfWidthConstraint])
        NSLayoutConstraint.activateConstraints([fullWidthConstraint])
    }
}

iOS 9 + Xcode 7 + 上进行测试。

答案 1 :(得分:2)

我将描述如何在两种布局之间进行简单的切换。

当屏幕旋转时,Autolayout会应用具有更高优先级的已安装默认布局。 Constraint是否处于活动状态并不重要。因为,在旋转时,会重新安装故事板上的高优先级布局并且active = true。 因此,即使您更改了活动状态,也会在旋转时应用默认布局,但无法保留任何布局。

切换两个布局,而不是切换活动状态。 在两种布局之间切换时,请使用" priority"而不是"活跃"。 这种方式不需要担心活动状态。 这很简单。

首先,在Storyboard上创建两个要切换的布局。检查两者是否已安装。 发生冲突错误,因为两个布局的优先级= 1000(必需)。 将要首先显示的布局的优先级设置为“高”。并将其他布局的优先级设置为低,将解决冲突错误。 将这些布局的约束关联为类的IBOutlet。 最后,只需在要更改布局的时间切换高和低之间的优先级。 请注意,请不要将优先级更改为" required"。优先级设置为必需的布局在此之后无法更改。

List<? extends AbstractClass> mylist = new ArrayList<>();

全宽的肖像 portrait 半宽景观 landscape

答案 2 :(得分:0)

您可以使用IB为大小类创建的约束进行必要的切换。诀窍是将折叠状态保持在变量中并更新约束事件中的约束以及特征集合更改事件。

Mockito.verify(foo).add("1");
Mockito.verify(foo).add(Mockito.anyString());