ios - 关于 autolayout 需要频繁变更的讨论
黄舟
黄舟 2017-04-17 13:26:09
[iOS讨论组]

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

在没有 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 的方式。大家有什么好的办法么?是不是我们的做法有问题?

黄舟
黄舟

人生最曼妙的风景,竟是内心的淡定与从容!

全部回复(2)
巴扎黑

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条件。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号