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

我不是在谈论帧属性,因为从那里你只能得到在 xib 视图的大小。我讨论的是视图由于其约束而调整大小的情况(可能是在旋转之后,或者是为了响应某个事件)。有办法得到它当前的宽度和高度吗?

我尝试遍历它的约束来寻找宽度和高度约束,但是这不是很干净,并且在存在内部约束时失败(因为我无法区分这两个约束)。而且,只有当它们实际上具有宽度和高度约束时,这种方法才有效,而如果它们依赖于其他约束来调整大小,则没有这种约束。

为什么这对我来说这么难 ARG!

83865 次浏览

框架仍然有效。最后,视图使用其框架属性进行布局。它根据所有的约束来计算框架。约束只用于初始布局(以及任何时候在视图上调用 layoutSubviews,比如在旋转之后)。然后,位置信息在帧属性中。还是你看到的不是这样?

答案是 [view layoutIfNeeded]

原因如下:

您仍然可以通过检查 view.bounds.size.widthview.bounds.size.height(或者框架,这是等价的,除非您正在使用 view.transform)来获得视图的当前宽度和高度。

如果您想要的是现有约束所隐含的宽度和高度,那么答案就是不要手动检查约束,因为这将需要您重新实现自动布局系统的整个约束解决逻辑,以便解释这些约束。相反,您应该做的只是 要求自动布局更新该布局,这样它就可以解决约束,并用正确的解决方案更新 view.bound 的值,然后检查 view.bound。

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

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

您提出了第二个问题: “如果没有直接引用,如何更改高度/宽度约束?”.

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

我有一个类似的问题,我需要添加一个顶部和底部边界的 UITableView,调整大小的基础上,其约束设置在 UIStoryboard。我能够使用 - (void)viewDidLayoutSubviews访问更新的约束。这非常有用,因此您不需要对视图进行子类化并重写其布局方法。

/*** 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方法调用该方法,只能正确绘制顶部边框,因为底部边框在屏幕外的某个地方。

使用 -(void)viewWillAppear:(BOOL)animated和调用 [self.view layoutIfNeeded];-它的工作原理,我已经尝试。

because if you use -(void)viewDidLayoutSubviews it will work definitely but this method is called every time your UI demands updations/changes. Which will get hard to manage. Soft key is you use a bool variable to avoid such loop of calls. better use viewWillAppear. Remember viewWillAppear will also be called if view is loaded back again (without reallocating).

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

只要覆盖该方法:

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

如果是 UITableViewCell 或 UICollectionViewCell,则创建单元格的子类并重写相同的方法:

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