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

しかし、私の問題は、左右のギャップを管理しながら、高さが固定されているため、iPhone6および6Plusでは伸びてしまうことです。画面サイズに応じてサイズを大きくするにはどうすればよいですか?これはアスペクト比かもしれないと思いますが、コードでアスペクト比の制約を設定するにはどうすればよいですか?


2
この回答を確認してください:stackoverflow.com/a/12526630/3202193
Ashish Kakkad 2015

回答:


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)任意のfloat値を使用できます。ありがとう。

Swift3.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」が原因でアプリを終了します。理由:「乗数は有限ではありません!それは違法です。乗数:ナン」
IRD

2
つまり、高さが100、幅が200で、コードで乗数0.5を指定した場合、他の制約を変更して高さが150に増加すると、幅は自動的に300に増加します。ただし、これを行うには、幅や高さなど、ビューの1つの制約を増やします。
Mahesh Agrawal 2015

1
高さ:幅= 1:2、つまり0.5が必要です。
Mahesh Agrawal 2015

3
プログラム的に制約を設定する前にこの行を追加することを忘れないでください: [self.yourview setTranslatesAutoresizingMaskIntoConstraints:NO];
atulkhatri

1
制約を使用すると、フレームサイズはすべてゼロでした。代わりに、アスペクト比を取得するために、次を使用しましたself.yourview.intrinsicContentSize
Phlippie Bosman 2017

89

レイアウトアンカーは、プログラムで制約を設定するための最も便利な方法です。

ボタンに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以降では、addConstraint(:)を呼び出す代わりに、NSLayoutConstraintのisActiveプロパティを使用する必要があります。aspectRatioConstraint.isActive = true
dvdblk 2017

.width最初の属性として使ってみませんか?結果はattr2 * multiplier 、アスペクト比はですwidth / height。したがってwidth = height * aspectRatio、を.height最初の属性に、aspectRatioをにするmultiplierと、結果は完全に逆になります。
キミチウ

13

InterfaceBuilderのデザイン時に「高さ制約」を設定できます。「ビルド時に削除」をチェックするだけで、アプリが実行されるときに削除されます。

ここに画像の説明を入力してください その後、たとえばviewDidLoadメソッドで「アスペクト比」制約を追加できます。

Xamain.iOS for "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)
のMichałZiobro

1
1. toItemパラメータがに設定されている:これは確かにタイプのエレガントな解決策禁じる夫婦で.selfはなく、self2、コメントでの使用をしなければならないview.aspectRation(1.0/1.0).isActive = true 、私は5 Xcodeの10.2.1スウィフトでこれをテストした
パンカジKulkarniさん

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とそのコンテンツモードではなく、自動レイアウトと制約に関するものです。Interface Builderから、アスペクト比の制約を設定できます。これにより、最後に乗数を使用して幅と高さの制約が作成されます。
グンハン

@Gunhanの質問は、プログラムで設定する方法に関連しています。したがって、Interface Builderで設定できることは知っておくと便利ですが、この質問とは無関係です。
valeriana

あなたは私が以前に言ったことを誤解したと思います。この質問では、誰もImageViewについて話していません。ITは自動レイアウトと制約に関するものであり、プログラムで作成する必要があります。私が言ったことは、Interface Builderで設定すると、幅と高さの制約が作成されるということでした。IB経由で作成するようには言わなかった。プログラムで同じことを行うには、次のようにそれを作成する必要がありview.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: aspectRatio, constant: 0)そう
Gunhan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.