总之,我的问题是:我可以在编程上使用autolayout同时调整UIView的框架吗?
是的,这可以实现。
如果您设置视图的translatesAutoresizingMaskIntoConstraints = YES
,则在运行时,对setFrame:
的调用会自动转换为基于视图当前autoresizingMask
的布局约束。这使您可以将基于框架的布局与基于约束的布局混合使用。
例如,您可以使用自动布局定义视图的所有子视图的布局,但仍然可以调用setFrame:
来设置视图本身的大小和位置。从您的角度来看,您正在使用自动布局和直接框架操作进行布局。但实际上,系统正在使用约束来处理所有内容。
但是,使用translatesAutoresizingMaskIntoConstraints
有一个重要的注意事项。
当您这样做时,您仍然需要确保这些自动约束可以满足其余的约束。
因此,例如,假设已经存在约束来确定您的视图的大小和位置,然后您还设置了translatesAutoresizingMaskIntoConstraints = YES
并调用了setFrame:
。对setFrame:
的调用将在视图上生成新的约束,这可能会与已经存在的约束冲突。
NSAutoresizingMaskLayoutConstraint
,那么你所看到的就是与自动约束冲突。这是一个容易犯的错误,因为translatesAutoresizingMaskIntoConstraints = YES
是默认值,所以如果你在代码中配置约束条件,如果不想要这些自动约束条件,就需要记得将其关闭。
相反地,假设已经存在约束条件来确定视图的大小和位置,但在调用setFrame:
之前设置了translatesAutoresizingMaskIntoConstraints = NO
。在这种情况下,setFrame:
调用将不会产生新的约束条件,因此不会在不同的约束条件之间发生冲突。然而,在这种情况下,仍然存在约束条件和你设置的框架值之间的“冲突”。在下一次自动布局被调用时,它会看到视图上已经存在的约束条件,计算出它们所需的框架值,并将框架设置为所需的值,从而覆盖你手动设置的值。
对我来说最容易的事情是将我想要移动/调整大小的视图从其父视图中移除,设置其frame
,然后重新添加它。例如,在UITableViewCell
子类中使用自定义UILabel
:
[cell.myLabel removeFromSuperview];
cell.myLabel.frame = someFrameIGenerated;
[cell.contentView addSubview:cell.myLabel];
有一个对我有效的方法是为我的约束添加 IBOutlet
,然后在视图控制器中更改这些约束的 constant
属性。
例如,要更改视图的 x 坐标,请从该视图的前导约束创建一个到您的控制器的 outlet。换句话说,创建一个 outlet:@IBOutlet var labelXOrigin: NSLayoutConstraint!
。然后,当您想要调整 x 位置时,只需执行类似以下操作:
self.labelXOrigin.constant = 20.0 // Or whatever origin you want to set.
- (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];
}
我不确定,但我认为如果您使用这个解决方案,切换一个方向到另一个方向可能会导致问题。
translatedAutoresizingMaskIntoConstraints=true
进行操作时看到这些警告,则很可能已经存在一些约束(可能是在IB中设置的),试图控制该视图的框架。这些旧约束与从自动调整大小掩码自动生成的约束相互作用。在这种情况下,答案是删除这些旧约束。如果您只是为了让IB在设计时保持安静而在IB中添加它们,那么可以将它们变成“占位符”以将其删除。 - algalCGRect
。在这种情况下,您需要在其他视图完成其自动布局传递之后执行帧计算。在视图控制器中,viewDidLayoutSubviews
是这样做的地方。在自定义视图中应该使用layoutSubviews
。在两种情况下,您都应该在super
调用之后放置您的框架计算。也许将此添加到答案中会很有价值,但我希望这是一个有用的评论! - Benjohn