iOS: UIButton 自动布局大小为零
iOS: UIButton Autolayout size is zero
使用自动布局我想了解为什么会发生以下情况:创建一个简单的 UIButton 并设置其标题。但是,即使我希望设置视图的固有内容大小并因此正确获取其框架 - 按钮的框架显示为 (0, 0, 0, 0)。我需要做什么才能获得按钮的帧值?
-(void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [[UIButton alloc] init];
[button.titleLabel setText:@"My button"];
//button frame is zero
}
然而,如果我要那样做,那么事情就会按预期进行:
-(void)viewDidLoad {
[super viewDidLoad];
UILabel *label = [[UILabel alloc] init];
[label setText:@"My label"];
[label sizeToFit];
//label frame has the expected width and height
}
将按钮添加为子视图并在子视图上调用 layoutIfNeeded
。之后访问其框架。
还要确保为 leading 和 top 添加约束以将按钮定位在其父视图中。
Autolayout 仅在布局通过后设置视图框架,它具有循环且不会在每次添加视图或修改约束时调用,这就是为什么有时您需要在特定视图上调用 -setNeedsLayout
的原因。
另一点是,如果您不使用界面构建器或以编程方式创建约束,自动布局会自动将视图自动调整大小掩码转换为约束(-translatesAutoresizingMaskIntoConstraints
属性)。
在这种情况下,如果您设置文本,您将强制视图表达其内在内容大小,基本上就是标签的大小,如果内在内容大小不与其他约束冲突,它会获胜,但您只能询问布局通过后的按钮大小。在对 super class
调用相同的方法后,尝试检查 .viewDidLayout
内的按钮大小
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.translatesAutoresizingMaskIntoConstraints = NO;
[button setTitle:@"My button" forState:UIControlStateNormal];
[self.view addSubview:button];
}
- (void)viewDidLayoutSubviews {
//check frame of button
}
正如@Andrea 所说:因为您没有在 IB 中添加按钮,所以它默认使用 autoResizingMask,这将保留按钮初始化时使用的零尺寸框架。
如果你想让自动布局工作,你需要设置
button.translatesAutoresizingMaskIntoConstraints = NO;
就在调用 -addSubview:
之前。
此外,您必须至少添加 1 个水平约束和 1 个垂直约束才能定位按钮。即使在您这样做之后,按钮的框架也只会在下一次布局通过后设置,您可以通过调用 -layoutIfNeeded
.
手动启动
使用自动布局我想了解为什么会发生以下情况:创建一个简单的 UIButton 并设置其标题。但是,即使我希望设置视图的固有内容大小并因此正确获取其框架 - 按钮的框架显示为 (0, 0, 0, 0)。我需要做什么才能获得按钮的帧值?
-(void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [[UIButton alloc] init];
[button.titleLabel setText:@"My button"];
//button frame is zero
}
然而,如果我要那样做,那么事情就会按预期进行:
-(void)viewDidLoad {
[super viewDidLoad];
UILabel *label = [[UILabel alloc] init];
[label setText:@"My label"];
[label sizeToFit];
//label frame has the expected width and height
}
将按钮添加为子视图并在子视图上调用 layoutIfNeeded
。之后访问其框架。
还要确保为 leading 和 top 添加约束以将按钮定位在其父视图中。
Autolayout 仅在布局通过后设置视图框架,它具有循环且不会在每次添加视图或修改约束时调用,这就是为什么有时您需要在特定视图上调用 -setNeedsLayout
的原因。
另一点是,如果您不使用界面构建器或以编程方式创建约束,自动布局会自动将视图自动调整大小掩码转换为约束(-translatesAutoresizingMaskIntoConstraints
属性)。
在这种情况下,如果您设置文本,您将强制视图表达其内在内容大小,基本上就是标签的大小,如果内在内容大小不与其他约束冲突,它会获胜,但您只能询问布局通过后的按钮大小。在对 super class
.viewDidLayout
内的按钮大小
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.translatesAutoresizingMaskIntoConstraints = NO;
[button setTitle:@"My button" forState:UIControlStateNormal];
[self.view addSubview:button];
}
- (void)viewDidLayoutSubviews {
//check frame of button
}
正如@Andrea 所说:因为您没有在 IB 中添加按钮,所以它默认使用 autoResizingMask,这将保留按钮初始化时使用的零尺寸框架。
如果你想让自动布局工作,你需要设置
button.translatesAutoresizingMaskIntoConstraints = NO;
就在调用 -addSubview:
之前。
此外,您必须至少添加 1 个水平约束和 1 个垂直约束才能定位按钮。即使在您这样做之后,按钮的框架也只会在下一次布局通过后设置,您可以通过调用 -layoutIfNeeded
.