使用自动布局时,UIButton停止工作

7
我已经编写了一个简单的视图控制器程序,其中只有两个按钮。如果我采用老式的方式并为布局设置框架大小,则一切都很好。但是,如果我使用自动布局约束进行布局,则按钮显示完美,但它们不响应按下操作。它们甚至不会高亮显示。我的loadview方法如下所示,以使按钮无法正常工作。如果取消注释框架设置代码并注释掉约束添加,则按钮开始按预期响应按下操作。有人知道发生了什么吗?我希望将代码库中所有旧的硬编码布局转换为基于约束的布局,但似乎在第一个障碍处就失败了。
- (void)loadView {
    self.view = [UIView new];
    self.view.translatesAutoresizingMaskIntoConstraints = NO;

    self.navigationItem.title = @"Landing Page";

    UIButton *buildExercisesButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.buildExercisesButton = buildExercisesButton;
//    buildExercisesButton.frame = CGRectMake(20, 312, 164, 44);
    self.buildExercisesButton.translatesAutoresizingMaskIntoConstraints = NO;
    [self.buildExercisesButton setTitle:@"Build Exercises" forState:UIControlStateNormal];
    [self.buildExercisesButton addTarget:self action:@selector(buildExercisesButtonPressed) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.buildExercisesButton];

    UIButton *organiseExercisesButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.organiseExercisesButton = organiseExercisesButton;
//    organiseExercisesButton.frame = CGRectMake(192, 312, 164, 44);
    self.organiseExercisesButton.translatesAutoresizingMaskIntoConstraints = NO;
    [self.organiseExercisesButton setTitle:@"Organise Exercises" forState:UIControlStateNormal];
    [self.organiseExercisesButton addTarget:self action:@selector(organiseExercisesButtonPressed) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.organiseExercisesButton];

    NSDictionary *variables = NSDictionaryOfVariableBindings(buildExercisesButton, organiseExercisesButton);
    NSArray *constraints =
            [NSLayoutConstraint constraintsWithVisualFormat:@"|-[buildExercisesButton(organiseExercisesButton)]-[organiseExercisesButton]-|"
                                                    options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom
                                                    metrics:nil
                                                      views:variables];
    [self.view addConstraints:constraints];

    constraints =
            [NSLayoutConstraint constraintsWithVisualFormat:@"V:[buildExercisesButton]-|"
                                                    options:0
                                                    metrics:nil
                                                      views:variables];
    [self.view addConstraints:constraints];
}

在viewDidAppear方法中,我打印了按钮的框架。它们给出了一些奇怪的值,我不知道是否相关。实际上,这些按钮是在屏幕中央并排显示的。
buildExercisesButton: {{20, -63}, {164, 44}}
organiseExercisesButton: {{192, -63}, {164, 44}}

嗯...当我复制了你的代码后,它运行得很好。我的记录是:构建框架是:{{20, 397}, {136, 44}}组织框架是:{{164, 397}, {136, 44}}。 - rdelmar
5个回答

3

您需要为添加按钮的视图定义约束条件,或将 translatesAutoresizingMaskIntoConstraints 属性设置为 YES


谢谢 Raphael,那就是问题所在。 - John Holcroft

2
如果您仅使用Storyboard进行自动布局,请尝试增加垂直内容吸附优先级和垂直压缩阻力优先级:

为什么?那做了什么? - Le-roy Staines

1

看起来问题出在第二行:

self.view.translatesAutoresizingMaskIntoConstraints = NO;

这行代码导致视图不是全屏,而是从中心附近开始。因此,虽然按钮出现在屏幕中央附近,但它们实际上在包含视图之外。当我删除这行代码后,一切都开始正常工作。
我想我发现了一个关于translatesAutoresizingMaskIntoConstraints的问题。尽管您必须关闭它才能使用约束,但仅对使用约束的确切视图进行操作,而不是包含视图(除非它也使用约束)。在这种情况下,我关闭了包含视图上的translatesAutoresizingMaskIntoConstraints,但不应该这样做,因为它没有针对它的约束。

1
我遇到了同样的问题。在我的情况下:
self.view
 \- ...
  \_self.wrapper
       \_self.button

代码不起作用:

NSDictionary *metrics = @{@"padding":[NSNumber numberWithFloat:kGridPadding]};

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[head]-padding-[wrapper]-|" options:0 metrics:metrics views:views]];

原因是 'wrapper' 的高度为 0,尽管按钮仍然可见。因此,可以通过给予足够的宽度和高度来解决此问题,如下所示:
NSDictionary *metrics = @{@"padding":[NSNumber numberWithFloat:kGridPadding],
                          @"screenHeight":[NSNumber numberWithFloat:self.view.bounds.size.height]};

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[head]-padding-[wrapper(screenHeight)]-|" options:0 metrics:metrics views:views]];

--> 更好的方式是使包装器的高度自动增加,但我现在不知道如何做到这一点?


如果你使用视图调试器,你会看到念亮所说的包装器。对我而言,它是持有不响应轻击按钮的视图的父视图。它的高度为0。为了解决这个问题,我只需向按钮的容器视图添加一个高度约束即可。 - Matt Hudson

1
似乎 UIButton 的框架超出了屏幕。触摸事件取决于命中按钮而不是按钮图像,这就是为什么它们没有响应的原因。
为什么要使用自动布局而不是设置框架?

是的,那就是问题所在。我已经写了一个完整的解释作为另一个答案。我使用自动布局的原因是我相信它是未来的趋势。当只有少量潜在的屏幕尺寸和维度时,硬编码布局还可以,但现在有了各种设备、iOS 7和本地化等因素,就不行了。我的大多数视图都是通过编程方式组合起来的,因此Interface Builder也没有什么用处。因此,我正在努力克服使用代码中的自动布局的学习曲线。 - John Holcroft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接