首页 > 关于 autolayout 需要频繁变更的讨论

关于 autolayout 需要频繁变更的讨论

希望搞一次开放性的讨论,先描述问题:

在没有 autolayout 之前,我们在频繁变更 view 大小或者位置时,可以直接通过设置 view.frame,如:

view.frame = CGRectMake(x, y, width, height);

这是 view 的位置和大小都将按照最新的 frame 来展示。

但是,自从使用 autolayout 的最大困惑就是,autolayout 同一优先级的 constraint 不允许冲突,否则将会报错。所以如果一个 view 要频繁变更样式,不得不频繁的 addConstraint 和 removeConstraint,并且为了能够准确 removeConstraint,我们不得不在 addConstraint 时,保存 NSAutolayoutConstraint 的对象。
例如有这样的需求:
当键盘弹起时,我需要 view 的高度减小到 100.0;当键盘消失时,view 的高度变成 300.0。而现在的做法是,将高度 300 的 constraint 的优先级设定为 250 —— LOW,当键盘弹起时,我再给他 addConstraint,变成 300.0,优先级为 1000,同时缓存此 Constraint,并用一个 Dictionary 保存此 Constraint,记为 consHeight300,目的是为了在键盘消失时方便取出该对象,然后

[view removeConstraint:consHeight300];

这种频繁的新增到 Dictionary,然后 removeConstraint,而且你可能还要频繁的管理该 Dictionary 的值,我觉得其实非常麻烦,真心不如 frame 的方式。大家有什么好的办法么?是不是我们的做法有问题?


constraint 有一个唯一可以修改的属性 constant,我承认它的名字确实很具有迷惑性。。。
以题主提到的高度问题为例,可以保存这个高度 constraint 的引用,在键盘出现和收起时

objc- (void)keyboardDidShowNotification
{
    self.viewHeightConstraint.constant = 100.f;
    [self.myView layoutIfNeed];
}

- (void)keyboardDidHideNotification
{
    self.viewHeightConstraint.constant = 300.f;
    [self.myView layoutIfNeed];
}

如果是很复杂的 UI,constant 的修改不足以满足需求,那么频繁添加和移除 constraints 是不可避免的。但不得不说,这时候先要就 UI 设计小小做一下重新思考:)

补充:autolayout 同一优先级的 constraint 似乎并不是不允许冲突,而是 required 的 constraint 不允许冲突,因为它们必须全部满足。autolayout 底层的casowarry 算法我还没看懂(数学退化太严重了=。=),但稍微看了一下算法原作者的论文,优先级较低的约束是可以不全部满足的。
这是一个casowarry 的 Python 实现,题主可以参考下。


一句话: 题主不知道Constraint有constant属性。

1. 关于楼主所举例的键盘弹出弹入的问题

@NSFish 已经说的很详细了, 直接在监听函数中修改constant的值既能解决问题

2. 关于autolayout和frame

autolayout是一个远远超越frame的工具。我们以autolayout思维来解构frame的实现基础, view距父节点上边距为定值、距父节点左边距为定值、高度为定值、宽度为定值, 我们通过autolayout就能轻松构建这种约束条件

json Constraint: leading space to superview,
 Constraint: top space to superview, 
 Constraint: width, 
 Constraint: height

对view添加上面这4个constraint后我们就能像使用frame一样来使用autolayout。所以autolayout是frame的超集,如果autolayout搞不定的UI, frame也绝无可能可以搞定。

就我个人使用autolayout来看, view就应该只有一套固定的Constraint, 初始化完成后就不应该再有addConstraint 和 removeConstraint之类的操作, 一个view有多套Constraint逻辑反而维护和修改都是非常麻烦的事情, 如果必须有这样的操作就应该重新设计你的Constraint条件。

【热门文章】
【热门文章】