如何使用自动布局约束获取视图的当前宽度和高度?

我不是在谈论框架属性,因为从那里你只能在xib中获得视图的大小。 我正在讨论什么时候视图是由于其约束(也许在轮换或响应事件之后)resize的。 有没有办法获得当前的宽度和高度?

我尝试通过约束来寻找宽度和高度约束,但是这不是很干净,并且在存在内在约束时失败(因为我无法区分这两者)。 此外,只有在实际上具有宽度和高度约束的情况下才起作用,如果它们依赖于其他约束来resize,则它们不起作用。

为什么这对我来说如此困难。 ARG!

答案是[view layoutIfNeeded]

原因如下:

您仍然通过检查view.bounds.size.widthview.bounds.size.height (或者相当于除非使用view.transform的框架)来获取视图的当前宽度和高度。

如果你想要的是现有约束所包含的宽度和高度,答案不是手动检查约束,因为这需要你重新实现自动布局系统的整个约束求解逻辑。 相反,你应该做的只是要求自动布局更新该布局 ,以便解决约束,并用正确的解决scheme更新view.bounds的值,然后检查view.bounds。

你如何要求自动布局更新布局? 如果你想自动布局更新下一轮运行循环的布局,请调用[view setNeedsLayout]

但是, 如果您希望立即更新布局,那么您可以在当前函数中稍后立即访问新的边界值 ,或者在运行循环开始之前的其他位置立即访问新的边界值 ,则需要调用[view setNeedsLayout][view layoutIfNeeded]

你问了第二个问题:“如果我没有直接引用它,我该如何改变高度/宽度约束?”。

如果在IB中创build约束,最好的解决scheme是在视图控制器或视图中创build一个IBOutlet,以便直接引用它。 如果你在代码中创build了约束,那么当你创build一个内部弱属性的时候,你应该保持一个引用。 如果其他人创build了约束,那么您需要通过检查视图上的view.constraints属性以及可能的整个视图层次结构来查找它,并实现查找关键NSLayoutConstraint的逻辑。 这可能是错误的方法,因为它也有效地要求你确定哪个特定的约束决定了边界的大小,当不能保证是对这个问题的简单回答的时候。 最终的界限值可以是一个非常复杂的多约束系统的解决scheme,具有多个优先级等,因此没有单个约束是最终值的“原因”。

我有一个类似的问题,我需要添加一个顶部和底部的边界到一个UITableView ,根据UIStoryboard约束设置进行UIStoryboard 。 我能够通过- (void)viewDidLayoutSubviews访问更新后的约束。 这很有用,所以你不需要为视图创build子类并覆盖它的布局方法。

 /*** SET TOP AND BOTTOM BORDERS ON TABLE VIEW ***/ - (void)addBorders { CALayer *topBorder = [CALayer layer]; topBorder.frame = CGRectMake(0.0f, self.tableView.frame.origin.y, 320.0f, 0.5f); topBorder.backgroundColor = [UIColor redColor].CGColor; CALayer *bottomBorder = [CALayer layer]; bottomBorder.frame = CGRectMake(0.0f, (self.tableView.frame.origin.y + self.tableView.frame.size.height), 320.0f, 0.5f); bottomBorder.backgroundColor = [UIColor redColor].CGColor; [self.view.layer addSublayer:topBorder]; [self.view.layer addSublayer:bottomBorder]; } /*** GET AUTORESIZED FRAME DIMENSIONS ***/ - (void)viewDidLayoutSubviews{ [self addBorders]; } 

没有从viewDidLayoutSubview方法调用方法,只有顶部边框被正确绘制,因为底部边框在屏幕外某处。

对于那些可能仍然面临这样的问题,特别是TableviewCell。

只需重写该方法:

 -(void)layoutSubviews { //your code here like drawing a shadow } 

在UITableViewCell或UICollectionViewCell的情况下创build单元格的子类并重写相同的方法:

 -(void)layoutSubviews { //your code here like drawing a shadow } 

该框架仍然有效。 最后,该视图使用其框架属性来展示自己。 它基于所有约束来计算该帧。 约束仅用于初始布局(任何时候layoutSubviews在旋转之后在视图上调用)。 之后,位置信息在框架属性中。 还是你看到其他?

使用-(void)viewWillAppear:(BOOL)animated并调用[self.view layoutIfNeeded]; – 它已经尝试过了

因为如果你使用-(void)viewDidLayoutSubviews它肯定会工作,但是这个方法在你的UI每次需要更新/更改的时候被调用。 哪个会变得难以pipe理。 软键是你使用一个布尔variables来避免这样的调用循环。 更好地使用viewWillAppear 。 还记得viewWillAppear也将被调用,如果再次加载视图(不重新分配)。