如何在iOS中以编程方式设置纵横比约束?


85

我已经为视图控制器使用了自动布局。我已经在约束中设置了V和H位置,但是我想知道当按钮变为5s,6和6 Plus时如何增加按钮的大小。这是我为登录按钮添加约束的方式:

NSArray *btncon_V=[NSLayoutConstraint constraintsWithVisualFormat:@"V:[btnLogin(40)]" options:0 metrics:nil views:viewsDictionary];
[btnLogin addConstraints:btncon_V];

NSArray *btncon_POS_H=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[btnLogin]-100-|" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:btncon_POS_H];


NSArray *btncon_POS_V=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-70-[Title]-130-[lblFirst]-0-[lblSecond]-20-[textusername]-10-[txtpassword]-10-[btnLogin]" options:0 metrics:nil views:viewsDictionary];

[self.view addConstraints:btncon_POS_V];

但是我的问题是,尽管它可以控制左右间隙,但由于高度是固定的,因此在iPhone 6和6 Plus中变得越来越张紧。如何根据屏幕尺寸增加尺寸?我认为这可能是纵横比,但是如何在代码中设置纵横比约束?


Answers:


84

像这样。尝试一次。

[self.yourview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.yourview addConstraint:[NSLayoutConstraint
                                  constraintWithItem:self.yourview
                                  attribute:NSLayoutAttributeHeight
                                  relatedBy:NSLayoutRelationEqual
                                  toItem:self.yourview
                                  attribute:NSLayoutAttributeWidth
                                  multiplier:(self.yourview.frame.size.height / self.yourview.frame.size.width)
                                  constant:0]];

或者(self.yourview.frame.size.height / self.yourview.frame.size.width)可以使用任何浮点值代替。谢谢。

斯威夫特3.0-

self.yourview!.translatesAutoresizingMaskIntoConstraints = false
self.yourview!.addConstraint(NSLayoutConstraint(item: self.yourview!,
                                          attribute: NSLayoutAttribute.height,
                                          relatedBy: NSLayoutRelation.equal,
                                          toItem: self.yourview!,
                                          attribute: NSLayoutAttribute.width,
                                          multiplier: self.yourview.frame.size.height / self.yourview.frame.size.width,
                                          constant: 0))

由于未捕获的异常“ NSInternalInconsistencyException”,它给了我这个错误正在终止应用程序,原因:“乘数不是有限的!那是非法的。multiplier:nan'–
IRD

2
这意味着在例如高度为100且宽度为200且您给我的代码赋予乘数0.5的情况下,那么如果您的高度通过更改任何其他约束而增加到150,则宽度将自动增加到300。但是要做到这一点增加视图的一种约束,例如宽度或高度。
Mahesh Agrawal

1
它将采用height:width = 1:2即0.5。
Mahesh Agrawal

3
以编程方式设置任何约束之前,请不要忘记添加此行: [self.yourview setTranslatesAutoresizingMaskIntoConstraints:NO];
atulkhatri

1
使用约束时,我的帧大小全部为零。为了获得长宽比,我使用了self.yourview.intrinsicContentSize
Phlippie Bosman

88

布局锚点是通过编程设置约束的最便捷方法。

假设您要为按钮设置5:1的宽高比,则应使用:

button.heightAnchor.constraint(equalTo: button.widthAnchor, multiplier: 1.0/5.0).isActive = true

这是完整的代码:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = UIButton(type: .custom)
        button.setTitle("Login", for: .normal)
        button.backgroundColor = UIColor.darkGray

        self.view.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false

        let margins = view.layoutMarginsGuide

        button.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 20.0).isActive = true
        button.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: -20.0).isActive = true
        button.bottomAnchor.constraint(equalTo: margins.bottomAnchor, constant: -20.0).isActive = true
        button.heightAnchor.constraint(equalTo: button.widthAnchor, multiplier: 1.0/5.0).isActive = true
    }

}

这是上面编写的代码实现的结果。您可以看到该按钮在各种设备上保持其5:1的纵横比:

结果视图


14

斯威夫特3:

yourView.addConstraint(NSLayoutConstraint(item: yourView,
                                          attribute: .height,
                                          relatedBy: .equal,
                                          toItem: yourView,
                                          attribute: .width,
                                          multiplier: 9.0 / 16.0,
                                          constant: 0))

1
对于iOS 8及更高版本,您应该使用NSLayoutConstraint的isActive属性,而不是调用addConstraint(:)。aspectRatioConstraint.isActive = true
dvdblk

为什么不使用.width第一个属性?结果为attr2 * multiplier ,长宽比为width / height,因此width = height * aspectRatio,如果将放到.height第一个属性,将aspectRatio放到,multiplier则结果完全相反。
Kimi Chiu

12

您可以在Interface Builder中在设计时设置“高度约束”。只需选中“在构建时删除”,它就会在App运行时删除。

在此处输入图片说明 之后,您可以在viewDidLoad方法中添加“纵横比”约束。

在Xamain.iOS中,“ 16:9”看起来像这样:

    this.ImageOfTheDay.AddConstraint(NSLayoutConstraint.Create(
            this.ImageOfTheDay,
            NSLayoutAttribute.Height,
            NSLayoutRelation.Equal,
            this.ImageOfTheDay,
            NSLayoutAttribute.Width,
            9.0f / 16.0f,
            0));

或者,正如Mahesh Agrawal所说:

    [self.ImageOfTheDay addConstraint:[NSLayoutConstraint
                              constraintWithItem:self.ImageOfTheDay
                              attribute:NSLayoutAttributeHeight
                              relatedBy:NSLayoutRelationEqual
                              toItem:self.ImageOfTheDay
                              attribute:NSLayoutAttributeWidth
                              multiplier:(9.0f / 16.0f)
                              constant:0]];

12

UIView上的辅助扩展

extension UIView {

    func aspectRation(_ ratio: CGFloat) -> NSLayoutConstraint {

        return NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: self, attribute: .width, multiplier: ratio, constant: 0)
    }
}

用法是:

view.aspectRation(1.0/1.0).isActive = true


及用量:view.aspectRation(1.0 / 1.0)
米哈尔Ziobro

1
这的确是一个很好的解决方案禁止情侣类型:1. toItem参数设置为.self代替self2并在注释中的使用应view.aspectRation(1.0/1.0).isActive = true 我在Xcode 9.2.1斯威夫特5.测试此
潘卡库尔卡尼

3

我已经尝试了上面所有的答案,但是没有用,这是我的解决方案:3:

let newConstraint = NSLayoutConstraint(item: yourView, attribute: .width, relatedBy: .equal, toItem: yourView, attribute: .height, multiplier: 560.0/315.0, constant: 0)
yourView.addConstraint(newConstraint)
NSLayoutConstraint.activate([newConstraint])  
NSLayoutConstraint.deactivate(yourView.constraints)
yourView.layoutIfNeeded()

在添加新约束之前,应始终停用(可能会发生冲突)约束,以避免自动布局错误
John

0

对于视图,既有约束,也有属性。

纵横比是视图属性,因此您可以使用内容模式进行设置,如下所示

imageView.contentMode = .scaleAspectFit

这将实现的是一个视图不改变比如果例如

  • 高度或宽度大于屏幕显示的尺寸
  • 高度是硬编码的,因此将无法适应不同尺寸的屏幕。

问题不是关于ImageView及其内容模式,而是关于自动布局和约束。在“界面生成器”中,您可以设置长宽比约束,最后使用乘数创建宽度到高度约束。
Gunhan

@Gunhan问题与如何以编程方式设置它有关。因此,能够在界面生成器中进行设置非常高兴,但与该问题无关。
valeriana

我认为您误解了我之前所说的内容。在这个问题上,没有人在谈论ImageView。IT涉及自动布局和约束,并且必须以编程方式进行。我说的是在界面构建器中进行设置时,它会创建宽度到高度的约束。我没有告诉您通过IB创建它。要以编程方式执行相同的操作,您必须像view.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: aspectRatio, constant: 0)这样创建它
Gunhan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.