【问题标题】:How can I set aspect ratio constraints programmatically in iOS?如何在 iOS 中以编程方式设置纵横比约束?
【发布时间】:2015-09-28 19:18:15
【问题描述】:

我为我的视图控制器使用了自动布局。我已经在约束中设置了 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 中被拉伸。如何根据屏幕尺寸增加尺寸?我认为这可能是纵横比,但是如何在代码中设置纵横比约束?

【问题讨论】:

标签: ios autolayout constraints nslayoutconstraint


【解决方案1】:

Swift 5 解决方案,Xcode 12.4。需要 ios 9.0+

只需将您的高度限制固定到某个比例:

let aspectRatio: CGFloat = 9 / 16 // Example of ratio you want to apply
yourView.heightAnchor.constraint(equalTo: imageView.widthAnchor,
                                 multiplier: aspectRatio).activate()

【讨论】:

    【解决方案2】:

    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)
    • 这确实是一个优雅的解决方案,除了以下几种类型: 1. toItem 参数设置为.self 而不是self 2. 评论中的用法应该是view.aspectRation(1.0/1.0).isActive = true 我测试了这个在 Xcode 10.2.1 Swift 5 中。
    【解决方案3】:

    Layout Anchors 是最方便的以编程方式设置约束的方式。

    假设您想为按钮设置 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 的纵横比:

    【讨论】:

    • 很好的答案。这实际上不是 5:1,而是 1:5 纵横比:)
    【解决方案4】:

    像这样。尝试一次。

    [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),您可以使用任何浮点值。 谢谢。

    Swift 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”而终止应用程序,原因:“乘数不是有限的!那是违法的。乘数:nan'
    • 这意味着在这种情况下,如果高度为 100,宽度为 200,并且您使用我的代码给出了乘数 0.5,那么如果您的高度将通过更改任何其他约束增加到 150,那么宽度将自动增加到300. 但是要做到这一点,您需要增加视图的一个约束,例如宽度或高度。
    • 它将采用 height:width = 1:2 即 0.5。
    • 不要忘记在以编程方式设置任何约束之前添加这一行:[self.yourview setTranslatesAutoresizingMaskIntoConstraints:NO];
    • 使用约束时,我的帧大小都为零。为了获得纵横比,我使用了self.yourview.intrinsicContentSize
    【解决方案5】:

    我已经尝试了上述所有答案,但没有奏效,这是我使用 swift 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()
    

    【讨论】:

    • 您应该始终在添加新约束之前停用(可能冲突的)约束以避免自动布局错误
    【解决方案6】:

    斯威夫特 3:

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

    【讨论】:

    • 对于 iOS 8 及更高版本,您应该使用 NSLayoutConstraint 的 isActive 属性,而不是调用 addConstraint(:)。 aspectRatioConstraint.isActive = true
    • 为什么不使用.width 作为第一个属性?结果是attr2 * multiplier ,纵横比是width / height,所以width = height * aspectRatio,如果我们把.height放在第一个属性上,把aspectRatio放在multiplier上,结果完全相反。跨度>
    【解决方案7】:

    您可以在界面生成器的设计时设置“高度约束”。 只需选中“在构建时删除”,它会在应用程序运行时删除。

    之后,您可以添加“纵横比”约束,例如,在 viewDidLoad 方法中。

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

        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]];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多