我可以在运行时为特定的子视图禁用自动布局吗?


104

我有一个视图,需要以编程方式对其框架进行操作-这是一种文档视图,它包装到其内容,然后通过操纵框架原点在超级视图周围滚动和缩放。Autolayout在运行时与此作斗争。

完全禁用自动布局似乎有点困难,因为它可以合理地用于处理其他视图的布局。似乎我可能想要某种“空约束”。

Answers:


168

我有同样的问题。但是我已经解决了。
是的,您可以在运行时为特定的禁用自动布局UIView,而不是对Xcode 4.3及更高版本中默认设置的整个xib或Storyboard 禁用自动布局。

设置translatesAutoresizingMaskIntoConstraintsYES之前,先设置子视图的框架:

self.exampleView.translatesAutoresizingMaskIntoConstraints = YES;
self.exampleView.frame = CGRectMake(20, 20, 50, 50);

2
对于一些有很多观点的更复杂的情况,这似乎有些过分。对于这样简单的事情,这没关系。
esh

@MuhammadAamirALi删除子视图然后再添加回子视图可能会降低性能。我们可以归档更好的解决方案吗?
Nhat Dinh 2014年

2
@DinhNhat我澄清了答案。不需要删除和重新添加子视图。
Leandros

5
它向我显示警告:“无法同时满足约束条件。”
NSPratik 2015年

1
您保存了我的一天... translationsAutoresizingMaskIntoConstraints ...谁发明了像摇头
Tintenklecks15年

50

我有一个类似的问题,即Autolayout在运行时会覆盖我的某些帧设置(我有一个动态视图,在某些情况下,该视图推了一个新的视图控制器...按下然后按Back将重置初始视图)。

我通过将操作代码放入viewDidLayoutSubviewsView Controller 中来解决此问题。似乎在调用了约束mojo之后但在viewDidAppear之前调用了此方法,因此用户再合适不过了。


1
对于self.navigationItem.titleView无效。仍然不尊重框架的变化。
Henrik Erlandsson

1
如果您想弄混标题视图的框架,可以将其放在容器视图的内部,然后将容器视图添加为navigationItem的自定义视图。
jmstone617 2013年

2
这也为我工作。在发现此变通办法之前,我浪费了2h:22m将头撞在众所周知的墙上。
TMc 2014年

谢啦。我正在解决这个问题的第二天,现在可以了!
–'apostolov

28

也许只需设置translatesAutoresizingMaskIntoConstraintsYES(不添加影响该视图的其他约束),即可设置框架而无需与自动布局系统作斗争。


17

在iOS 8中,您可以将NSLayoutConstraint设置为活动或不活动。因此,如果使用接口构建器,则将所有约束添加到OutletCollection,然后使用以下方法激活或停用:

NSLayoutConstraint.deactivateConstraints(self.landscapeConstraintsPad)
NSLayoutConstraint.activateConstraints(self.portraitConstraintsPad)

我在这里使用的特定应用在纵向和横向模式下具有不同的约束,并且我会根据设备的旋转来激活/停用。这意味着我可以在两种方向的界面构建器中创建所有复杂的布局更改,并且仍然使用自动布局,而无需冗长的自动布局代码。

或者,您可以使用removeConstraints和addConstraints激活/停用。


抱歉,您劫持了这么一个老问题,但请问您是如何首先为不同布局添加布局约束的?我似乎找不到在界面生成器中启用/禁用约束的选项。还是只是为这两种布局都添加了约束,而忽略了界面构建器抱怨无效(覆盖)约束,又是否只是对约束进行了限制?
马尔特

好吧,您可以通过使用大小类来做到这一点:developer.apple.com/library/ios/recipes/…,但是我不能这样做,因为我也支持iOS 7,并且大小类也不完全支持iOS 7我通过降低冲突约束的优先级来做到这一点。不理想,但是会阻止警告。我认为无论如何我都是这样做的
。...– bandejapaisa

9

我不知道这是否对其他人有帮助,但是我写了一个类别来使此操作更方便,因为我发现自己做了很多事情。

UIView + DisableAutolayoutTemporarily.h

#import <UIKit/UIKit.h>

@interface UIView (DisableAutolayoutTemporarily)

// the view as a parameter is a convenience so we don't have to always
// guard against strong-reference cycles
- (void)resizeWithBlock:(void (^)(UIView *view))block;

@end

UIView + DisableAutolayoutTemporarily.m

#import "UIView+DisableAutoResizeTemporarily.h"
@implementation UIView (DisableAutoResizeTemporarily)

- (void)resizeWithBlock:(void (^)(UIView * view))block
{
    UIView *superview = self.superview;
    [self removeFromSuperview];
    [self setTranslatesAutoresizingMaskIntoConstraints:YES];
    __weak UIView *weakSelf = self;
    block(weakSelf);
    [superview addSubview:self];
}

@end

我这样使用它:

[cell.argumentLabel resizeWithBlock:^(UIView *view) {
    [view setFrame:frame];
}];

希望能帮助到你。


太棒了!我使用了代码的修改版本为任何UIView编写了一个简单的“ hideControl”功能。它基本上将UIView的高度设置为0,但至关重要的是,它使用您的代码使AutoLayout正确处理它(不同于使用“ someView.hidden = TRUE”)。因此,出现在隐藏控件下面并具有垂直间距的控件现在将在屏幕上向上移动以填充以前显示隐藏视图的位置。
Mike Gledhill 2014年

6

您可以在xib / storyboard中所需的UIView的“用户定义的运行时属性”中设置translatesAutoresizingMaskIntoConstraints类型Boolean“值是”。


2
  • 在4.5中打开项目
  • 选择情节提要
  • 打开文件检查器
  • 在“ Interface Builder文档”下,取消选中“使用自动版式”

如果要对某些视图使用自动布局,则可以拆分多个情节提要。


10
这将禁用整个情节提要/笔尖的自动布局。我正在寻找的是一种在理想的情节提要/笔尖中具有特定子视图的方式(最好是编程方式),而不使用自动布局,而让其余部分执行指定的情节提要/笔尖。
terriblememory

您可以使用多个情节提要板,并根据需要调用具有/不具有自动布局的情节提要板://初始化用于显示UIStoryboard *的storboard和局部视图控制器* sb = [UIStoryboard storyboardWithName:@“ Storyboard”包:[NSBundle mainBundle]]; DetailViewController * dvController = [sb InstantiateViewControllerWithIdentifier:entry.viewName];
Mike Bobbitt

1

对我来说,它可以以编程方式创建子视图,在我的情况下,自动布局使我需要围绕其中心旋转的视图陷入混乱,但是一旦以编程方式创建了该视图,它便可以正常工作。


1

我认为我有一个标签和一个文本。标签具有平移手势。在拖动过程中,标签移动良好。但是,当我使用文本框键盘时,标签会将其位置重置为自动布局中定义的原始位置。当我迅速为标签添加以下内容时,该问题已解决。我在viewWillAppear中添加了它,但是几乎可以在任何可以访问目标字段的地方添加它。

self.captionUILabel.translatesAutoresizingMaskIntoConstraints = true

0

这在没有情节提要或Xib文件的项目中发生了。所有100%的代码。我在底部有一个广告横幅,并希望视图边界在广告横幅处停止。加载后,视图将自动调整其大小。我尝试了此页面上的所有解决方案,但没有一个起作用。

我最终只是创建了一个高度缩短的子视图,并将其放入控制器的主视图中。然后,我所有的内容都进入了子视图。这样就很容易地解决了问题,而没有做任何看起来像是违反常规的事情。

我在想,如果您想要的视图不是填充窗口的正常大小,则应为此使用子视图。


0

我遇到过类似的情况,我加入了一个使用自动布局启动的项目,但是我需要对多个视图进行动态调整。这对我有用:

  1. 不要在界面生成器中布置视图或组件。

  2. 纯粹以编程方式添加您的视图(从alloc / init开始),并适当地设置其框架。

  3. 做完了


0

除了禁用自动布局之外,我只用要替换的帧计算新约束。在我看来,这是适当的方法。如果要调整依赖约束的组件,请相应地调整它们。

例如,如果两个视图(myView和otherView)之间的垂直约束为0,并且具有平移手势或用于调整myView高度的对象,则可以使用调整后的值重新计算约束。

self.verticalConstraint.constant = newMyViewYOriginValue - (self.otherView.frame.origin.y + self.otherView.frame.size.height);
[self.myView needsUpdateConstraints];

0

对于那些使用自动版式的人,请在此处查看我的解决方案。您应该先确定@IBOutlet要调整的约束,然后再更改其常数。


-16

如果是xib文件:

  1. 选择.xib文件
  2. 选择“文件的所有者”
  3. 显示实用工具
  4. 点击:“文件检查器”
  5. 在“ Interface Builder文档”下,禁用:“使用自动版式”

1
不,这将禁用整个布局的自动布局。我一直在寻找一种仅从自动布局系统中删除一个特定子视图的方法。
terriblememory
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.