Як можна програмно встановити обмеження співвідношення сторін у 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, оскільки висота фіксована. Як я можу збільшити розмір відповідно до розміру екрану? Я думаю, що це може бути співвідношення сторін, але як я можу встановити обмеження пропорцій у коді?


2
Перевірте цю відповідь: stackoverflow.com/a/12526630/3202193
Ashish Kakkad

Відповіді:


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))

Це видає мені цю помилку Припинення програми через непомічений виняток "NSInternalInconsistentcyException", причина: "Множник не обмежений! Це незаконно. множник: nan '
IRD

2
це означає, що у сценарії, наприклад, якщо висота 100, а ширина 200, і ви дали множник 0,5 з моїм кодом, то, якщо ваша висота збільшиться до 150, змінивши будь-яке інше обмеження, тоді ширина автоматично збільшиться до 300. Але для цього вам потрібно щоб збільшити одне обмеження виду, наприклад, ширину чи висоту.
Mahesh Agrawal

1
знадобиться висота: width = 1: 2, тобто 0,5.
Mahesh Agrawal

3
Не забудьте додати цей рядок перед тим, як програмувати будь-які обмеження: [self.yourview setTranslatesAutoresizingMaskIntoConstraints:NO];
atulkhatri

1
При використанні обмежень усі мої кадри були нульовими. Натомість для отримання пропорції я використавself.yourview.intrinsicContentSize
Фліппі Босмана

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 і новіших версій ви повинні використовувати властивість isActive NSLayoutConstraint замість виклику addConstraint (:). aspectRatioConstraint.isActive = true
dvdblk

Чому ви не використовуєте .widthяк перший атрибут? Результат - attr2 * multiplier це співвідношення сторін width / height, отже width = height * aspectRatio, якщо ми ставимо .heightдо першого атрибута, а aspectRatioдо - multiplierтоді результат повністю змінюється.
Кімі Чіу,

12

Ви можете встановити "Обмеження висоти" під час розробки в Interface Builder. Просто поставте прапорець біля пункту "Видалити під час збірки", і він видалить, коли додаток буде запущений.

введіть тут опис зображення Після цього ви можете додати обмеження "Співвідношення сторін", наприклад, у методі 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));

Або, як сказав Махеш Агравал :

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

12

Розширення Helper на 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
Це справді елегантне рішення, яке забороняє пару типів: 1. Параметр toItem встановлений .selfзамість self2. І використання в коментарі слід view.aspectRation(1.0/1.0).isActive = true перевірити. Я тестував це в Xcode 10.2.1 Swift 5.
Pankaj

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()

Завжди слід деактивувати (потенційно конфліктні) обмеження перед додаванням нових, щоб уникнути помилок
Джон

0

Для переглядів існують обмеження, а також є властивості.

пропорції - це властивість подання , тому ви можете встановити його за допомогою режиму вмісту, наприклад

imageView.contentMode = .scaleAspectFit

це дозволить досягти того, що подання не змінить співвідношення, якщо, наприклад

  • висота або ширина більші, ніж вмістяться на екрані
  • висота була жорстко закодована, і тому вона не зможе адаптуватися до різних розмірів екранів.

Питання не в ImageView та режимі його вмісту, а в автоматичному макеті та обмеженнях. За допомогою Конструктора інтерфейсів ви можете встановити обмеження пропорцій, яке в кінці створює обмежувач ширини та висоти за допомогою множника.
Гунхан,

@Gunhan питання стосується того, як встановити його програмно. Тож можливість встановити його у конструкторі інтерфейсів - це приємно знати, але це не має значення для цього питання.
valeriana

Думаю, ви неправильно зрозуміли те, що я сказав раніше. У цьому питанні ніхто не говорить про ImageView. Йдеться про автоматичне розміщення та обмеження, і це потрібно робити програмно. Що я сказав, коли ви встановлюєте його у конструкторі інтерфейсу, він створює обмеження ширини та висоти. Я не казав вам створювати його через IB. Щоб зробити те ж саме програмно, вам потрібно створити це якview.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: aspectRatio, constant: 0) так
Гунхан,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.