70

我想为我的所有按钮添加填充,因此我将 UIButton 子类化,并且在其他更改中,我想通过使用 setFrame 方法添加固定填充。一切正常,除了 setFrame。我检查了一下,发现如果我取消选中该视图上的“使用 AutoLayout”,那么我可以使用 setFrame,它可以工作。有没有解决的办法?我真的很想使用自动布局,因为它有助于使应用程序在 iphone 5 和更早的设备上看起来都不错。但我也想在我的子类中使用 setFrame,让我的生活更轻松。

总结一下,我的问题是:我可以使用自动布局并以编程方式调整 UIView 的框架吗?

4

5 回答 5

214

是的,这是可以做到的。

如果您设置视图的translatesAutoresizingMaskIntoConstraints = YES,则调用setFrame:会在运行时根据视图的 current 自动转换为布局约束autoresizingMask。这使您可以混合基于框架的布局和基于约束的布局。

例如,您可以使用 Auto Layout 来定义视图的所有子视图的布局,但仍然调用setFrame:来设置视图本身的大小和位置。从您的角度来看,您正在使用自动布局和直接框架操作混合进行布局。但系统实际上是使用约束来处理所有事情。

但是,使用translatesAutoresizingMaskIntoConstraints.

当你这样做时,你仍然需要确保这些自动约束可以满足你的其余约束

因此,例如,假设已经存在确定视图大小和位置的约束,然后您设置translatesAutoresizingMaskIntoConstraints = YES并调用了setFrame:. 调用setFrame:将在视图上生成新的约束,这可能会与已经存在的约束冲突。

(事实上​​,这个错误经常发生。如果您曾经看到一条日志消息抱怨约束冲突,并且其中一个约束是 a NSAutoresizingMaskLayoutConstraint,那么您看到的是与自动约束的冲突。这是一个简单的错误,因为translatesAutoresizingMaskIntoConstraints = YES是默认值,因此如果您在代码中配置约束,如果您不想要这些自动约束,则需要记住将其关闭。)

相比之下,再次假设已经存在确定视图大小和位置的约束,但是您translatesAutoresizingMaskIntoConstraints = NO在调用setFrame:. 在这种情况下,您的setFrame:调用不会产生新的约束,因此单独的约束之间不会有冲突。但是,在这种情况下,约束和您设置的帧值之间仍然存在“冲突” 。下次调用 Auto Layout 时,它会看到视图上已经存在的约束,计算它们需要的框架值,并将框架设置为本身所需的值,从而破坏您手动设置的值。

有关更多详细信息,请查看 Apple 的Cocoa 自动布局指南中的“采用自动布局”部分。

于 2012-11-24T09:01:40.430 回答
16

结果对我来说最简单的事情是从其父视图中删除我想要移动/调整大小的视图,设置它frame,然后将其添加回来。例如,UILabelUITableViewCell子类中进行自定义:

[cell.myLabel removeFromSuperview];
cell.myLabel.frame = someFrameIGenerated;
[cell.contentView addSubview:cell.myLabel];
于 2013-10-30T05:19:46.640 回答
3

对我有用的东西只是将IBOutlet我的约束添加到视图控制器,然后更改constant插座上的属性。

例如,要更改视图的 x 原点,请从该视图的前导约束设置一个出口到您的控制器。换句话说,创建一个 outlet @IBOutlet var labelXOrigin: NSLayoutConstraint!。然后,当您想调整 x 位置时,只需执行类似的操作

self.labelXOrigin.constant = 20.0 // Or whatever origin you want to set.
于 2016-03-20T21:59:11.060 回答
2

设置子视图框架的最佳方法是自动布局项目中的 viewWillLayoutSubviews 方法。

设置属性 translateAutoresizingMaskIntoConstraints = true 这将在视图确实出现或按钮上的选项卡设置后起作用,就在视图出现之后。

于 2016-06-14T07:00:40.810 回答
0

如果您的应用不支持多个设备方向。

viewDidLoad中设置要调整大小的视图的框架

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [aView setFrame:CGRectMake(15, 15, 100, 100)];
}

然后在viewDidLayoutSubviews

-(void)viewDidLayoutSubviews
{
    [self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
}

我不确定,但我认为如果您使用此解决方案,将一个方向切换到另一个方向可能会导致问题

于 2015-09-11T11:10:32.787 回答