【问题标题】:iOS: UIButton Autolayout size is zeroiOS:UIButton 自动布局大小为零
【发布时间】:2015-09-10 08:33:32
【问题描述】:

使用自动布局我想了解为什么会发生以下情况:创建一个简单的 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

}

【问题讨论】:

  • 你没有设置大小那么它总是为零。!!
  • 我没有设置尺寸,因为我使用的是自动布局。通过上面的代码 - 我希望有一个标题为“我的按钮”的按钮填充其内容。
  • 在自动布局中你必须设置约束
  • 好像少了[self.view addSubview:label],不加的话自动布局引擎中的计算不会通过

标签: ios objective-c uibutton autolayout


【解决方案1】:

Autolayout 仅在布局传递后设置视图框架,它具有循环,并且在您添加视图或修改约束时不会调用,这就是为什么有时您需要在特定视图上调用 -setNeedsLayout
另一点是,如果您不使用界面构建器或以编程方式创建约束,自动布局会自动将视图自动调整大小掩码转换为约束(-translatesAutoresizingMaskIntoConstraints 属性)。
在这种情况下,如果您设置文本,则强制视图表达其内在内容大小,这基本上是标签的大小,如果内在内容大小与其他约束不冲突,它会获胜,但您只能问布局通过后的按钮大小。在调用超类的相同方法后,尝试检查.viewDidLayout内的按钮大小

【讨论】:

  • 是的,我理解这一点,但是,UIButton 似乎在这个阶段没有应用其固有的内容大小。将按钮添加到主视图并在viewDidLayoutSubviews 上打印其大小再次显示 0 0...
  • 是否调用了[super viewDidLayoutSubviews]?添加标签后尝试在主视图上请求 setNeedsLayout
  • @pe60t0 如果不将标签添加为子视图,则不会通过自动布局计算
  • 我也应该在按钮上调用sizeToFit...这让我感到困惑。无论如何,谢谢 - 你的回答帮助我理解了这个问题。
  • 不。基本版本应该可以在不调用 sizeToFit 和 setNeedsLayout 的情况下工作。“应该”:D
【解决方案2】:
- (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
}

【讨论】:

    【解决方案3】:

    就像@Andrea 所说:因为您没有在 IB 中添加按钮,所以默认使用 autoResizingMask,它将保持按钮初始化时使用的零大小框架。

    如果你想让自动布局起作用,你需要设置

    button.translatesAutoresizingMaskIntoConstraints = NO;
    

    就在致电-addSubview: 之前。

    此外,您必须添加至少 1 个水平约束和 1 个垂直约束来定位按钮。即使您这样做了,按钮的框架也只会在下一个布局传递之后设置,您可以通过调用 -layoutIfNeeded 手动启动。

    【讨论】:

    • 但这不是真的——无论按钮在视图层次结构中的位置如何,都应该定义其固有的内容大小
    • @pe60t0 是的,它应该有一个 intrinsicContentSize,但 autoResizingMask 约束优先于此。如果你禁用 autoResizingMask,它就会启动。sizeToFit 对你有用,因为它手动将框架设置为intrinsicContentSize,但现在,即使内容(即标题或图像)发生变化,大小也不会自动更新。跨度>
    【解决方案4】:

    将按钮添加为子视图并在子视图上调用layoutIfNeeded。之后访问它的框架。

    还要确保为前导和顶部添加约束以将按钮定位在其父视图中。

    【讨论】:

    • 我可以理解一个视图需要有一个超级视图才能让布局引擎计算它的框架。然而,我不明白的是,如果我在上面的示例中使用标签而不是使用按钮 - 那么标签的大小就是我所期望的(在调用 sizeThatFits 之后)。我想象 UILabel 和 UIButton 的 intrinsicContentSize 将以相同的方式工作?
    猜你喜欢
    • 2012-12-18
    • 2016-02-24
    • 2014-04-29
    • 2016-06-04
    • 2015-08-10
    • 1970-01-01
    • 2019-04-13
    • 2014-12-02
    • 1970-01-01
    相关资源
    最近更新 更多