如何使用 NSLayoutConstraints 以编程方式将 UIView 中的 UIButtons 限制为比例宽度

How can I programatically constrain UIButtons in a UIView to proportional widths using NSLayoutConstraints

我正在尝试以编程方式创建自定义键盘。我已经设法让键盘的功能正常工作,但我正在努力以编程方式设置约束。

我已经设法找到代码来限制按钮在它们的行中大小相等,但无法对其进行足够的自定义以设置某些按钮的宽度(或比例宽度)。

这是当前键盘的图片

每一行都是一个单独的 UIView,其中填充了与每个键对应的 UIButton。然后我将每个视图内的按钮限制到它们的超级视图。

问题是我希望 space 按钮是屏幕的固定比例,并且第 4 行按钮的宽度相同(目前它们稍微宽一点,只有 9 个按钮而不是10 个)

虽然它是为 swift 编写的,但我已经从自定义键盘教程中改编了大量代码:here

- (void)addConstraintsToView: (UIView *)view {

    NSArray * buttons = view.subviews;

    for (UIButton * button in buttons) {

        NSInteger index = [view.subviews indexOfObject:button];

        NSLayoutConstraint * topConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTop multiplier:1.0f constant:1.0f];

        NSLayoutConstraint * bottomConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-1.0f];

        NSLayoutConstraint * leftConstraint;

        // If the first button in the row
        if (!index) {

            leftConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeLeft multiplier:1.0f constant:1.0f];
        }
        else {

            leftConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:buttons[index-1] attribute:NSLayoutAttributeRight multiplier:1.0f constant:1.0f];

            NSLayoutConstraint * widthConstraint = [NSLayoutConstraint constraintWithItem:buttons[0] attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0];

            [view addConstraint:widthConstraint];
        }

        NSLayoutConstraint * rightConstraint;

        // If the last button in the row
        if (index == buttons.count - 1) {

            rightConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeRight multiplier:1.0f constant:-1.0f];
        }
        else {

            rightConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:buttons[index+1] attribute:NSLayoutAttributeLeft multiplier:1.0f constant:-1.0f];
        }

        [view addConstraints:@[topConstraint, bottomConstraint, rightConstraint, leftConstraint]];
    }
}

这是当前将按钮限制为等宽的代码。

主要问题是,虽然有很多关于如何使用 NSlayoutConstraint 的'tutorials',但它们主要是为少数视图提供的。然后他们使用 then names 并设置约束。

This one is probably the best, this one has the problem that I mentioned, each button is allocated and used as a local variable. 相似但略有不同,而且观看次数要少得多。

为此,因为我们要添加更多的视图,然后将每个按钮作为其自己的变量会太复杂。如果我能弄明白的话,在循环中使用几个 if 语句会更优雅。

我真正希望它能够将某些按钮设置为固定宽度或比例宽度。例如,shift 按钮和删除按钮各占屏幕的 15%,或者 shift 和 delete 按钮固定为 48 像素。

如有任何帮助,我们将不胜感激

感谢@rdelmar 帮助我实现这个解决方案

虽然网上有很多关于 NSLayoutConstraints 的信息,但他们需要一些时间来适应。在这种情况下,我过度思考了问题,需要有人指出明显的问题。

所以在这种情况下,我试图改变按钮的宽度,所以我需要担心的是宽度限制。其他可以忽略。

这种情况下调整从其他来源获得的代码以满足我的需要的困难。

NSLayoutConstraint * widthConstraint;

if ([button.titleLabel.text isEqualToString:@"SHFT"] || [button.titleLabel.text isEqualToString:@"DEL"]) {

    // Make sure to set the button it is in relation to - in this case we can set it with relation to any of this middle buttons so buttons[1] is fine
    widthConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:buttons[1] attribute:NSLayoutAttributeWidth multiplier:1.5f constant:0];
}
else if ([button.titleLabel.text isEqualToString:@"space"]) {
    widthConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:buttons[1] attribute:NSLayoutAttributeWidth multiplier:3.0f constant:0];
}
else {
    widthConstraint = [NSLayoutConstraint constraintWithItem:buttons[1] attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0];
}

[view addConstraint:widthConstraint];

当我调整某些特定按钮时,我需要确保我只使用 if 语句更改它们的约束。然后使用倍增器,您可以将它们的宽度设置为视图中其他按钮的倍增器。

希望这对以后的人有所帮助,即使它只是将自定义键盘代码从 swift 翻译成 objective c

注意:请记住为要约束的视图设置 translatesAutoresizingMaskIntoConstraints。例如

view.translatesAutoresizingMaskIntoConstraints = NO;

如果你遗漏了它,那么即使你的约束条件都是正确的,它也不会起作用