Створення програмних обмежень макета


84

Я знаю, що багато людей вже задавали багато питань з цього приводу, але навіть маючи відповіді, я не можу змусити це працювати.

Коли я маю справу з обмеженнями на раскадровці, це легко, але в коді мені важко. Я намагаюся, наприклад, мати вигляд, який залишається праворуч і має висоту екрана відповідно до орієнтації екрана. Це мій код:

UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)];
myView.backgroundColor = [UIColor redColor];
[self.view addSubview:myView];
[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:0 metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

Це не задовольняє деяких обмежень. Я не бачу, що не так. Крім того, чому я не можу використовувати властивість like self.myViewзамість локальної змінної like myView?


Що таке vivi у наведеному вище коді?
iDev

14
Будь ласка, змініть назву на "iOS" замість "IOS" - остання стосується операційної системи комутатора / маршрутизатора Cisco. Збентежив мене. Дякую.
armani

1
Кілька питань щодо цього: (1) Яку помилку ви отримуєте, коли вона "не задовольняє певних обмежень"? (2) Ви перекладаєте авторозмір до обмежень на myView? (3) Що vivi(як запитував ACB)? (4) У вас є власність myViewоголошена self?
Тім

1
ih Тім, ну вибачте vivi, я прослухав занадто швидко ... це myView. Що ви маєте на увазі під перекладом? Все, що я роблю, це за кодом вище. Щодо властивості, у мене є деякі інші погляди, які оголошуються як властивість, але коли я реалізую той самий код для цього властивості, він аварійно
завершує роботу

Щоб тимчасово видалити обмеження з певного подання, зробіть це stackoverflow.com/questions/13388104/…
Сем Б

Відповіді:


106

При використанні автоматичного макета в коді, встановлення кадру нічого не робить. Тож той факт, що ви вказали ширину 200 у поданні вище, нічого не означає, коли ви встановлюєте для нього обмеження. Щоб набір обмежень подання був однозначним, йому потрібні чотири речі: положення х, положення у, ширина та висота для будь-якого даного стану.

Наразі у наведеному вище коді у вас лише два (висота щодо супервигляду та позиція у відносно супервигляду). На додаток до цього, у вас є два необхідні обмеження, які можуть конфліктувати залежно від того, як налаштовані обмеження суперпогляду представлення даних. Якщо супервигляд мав би необхідне обмеження, яке вказує, що його висота має якесь значення менше 748, ви отримаєте виняток "незадоволені обмеження".

Той факт, що ви встановили ширину подання до встановлення обмежень, нічого не означає. Він навіть не братиме до уваги старий кадр і буде обчислювати новий кадр, виходячи з усіх обмежень, які він вказав для цих подань. Маючи справу з авторозкладкою в коді, я зазвичай просто створюю нове представлення за допомогою initWithFrame:CGRectZeroабо просто init.

Щоб створити набір обмежень, необхідний для макета, який ви словесно описали у своєму питанні, вам потрібно буде додати деякі горизонтальні обмеження для обмеження ширини та положення x, щоб надати повністю заданий макет:

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:[myView(==200)]-|"
    options:NSLayoutFormatDirectionLeadingToTrailing
    metrics:nil
    views:NSDictionaryOfVariableBindings(myView)]];

Вербальний опис цього макета читається наступним чином, починаючи з вертикального обмеження:

myView заповнить висоту свого супервигляду верхньою та нижньою відступами, рівними стандартному пробілу. Мінімальна висота супервигляду myView - 748 пунктів. Ширина myView становить 200 балів і має правий відступ, що дорівнює стандартному пробілу проти його супервигляду.

Якщо ви просто хочете, щоб подання заповнювало всю висоту нагляду без обмеження висоти нагляду, тоді ви просто пропустили б (>=748)параметр у тексті візуального формату. Якщо ви вважаєте, що (>=748)параметр потрібен для того, щоб надати йому висоту - у цьому випадку ви цього не робите: закріпивши подання до країв суперперегляду за допомогою синтаксису bar ( |) або bar with space ( |-, -|), ви надаєте своєму виду y -позиція (закріплення подання на одному ребрі) та позиція y з висотою (закріплення подання на обох краях), таким чином задовольняючи ваші обмеження для подання.

Щодо Вашого другого питання:

Використовуючи NSDictionaryOfVariableBindings(self.myView)(якщо у вас була установка властивості для myView) та подаючи це у ваш VFL для використання self.myViewу вашому тексті VFL, ви, ймовірно, отримаєте виняток, коли авторозкладка намагається проаналізувати ваш текст VFL. Це пов’язано з позначенням крапок у ключах словника та системою, яка намагається використовувати valueForKeyPath:. Дивіться тут подібне запитання та відповідь .


Не забувайте, що деякі об'єкти, такі як UILabel, мають внутрішній розмір, і вам не потрібно встановлювати ширину або висоту цього об'єкта, а лише його позицію. Однак якщо ви встановите висоту або ширину, я вважаю, що це видаляє обидва, і вам доведеться подавати обидва.
Нік Тернер

Хоча ця відповідь не дала відповіді на моє запитання, вона допомогла мені щось зрозуміти. Дякуємо, що були! :)
Матей

1
На сьогоднішній день єдине стисле та читабельне введення автоматичного макета в Інтернеті.
Joey Carson

плз допоможіть мені моє запитання це ... я не знаю , як використовувати обмеження програмно stackoverflow.com/questions/36326288 / ...

61

Привіт, я багато використовую цю сторінку для обмежень та "як це зробити". Мені знадобилося вічно, щоб дійти до того, що зрозумів, що мені потрібно:

myView.translatesAutoresizingMaskIntoConstraints = NO;

щоб цей приклад запрацював. Дякую Userxxx, Роб М. та особливо larsacus за пояснення та код тут, це було безцінним.

Ось код повністю, щоб отримати наведені вище приклади:

UIView *myView = [[UIView alloc] init];
myView.backgroundColor = [UIColor redColor];
myView.translatesAutoresizingMaskIntoConstraints = NO;  //This part hung me up 
[self.view addSubview:myView];
//needed to make smaller for iPhone 4 dev here, so >=200 instead of 748
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:[myView(==200)]-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(myView)]];

11

Швидка версія

Оновлено для Swift 3

Цей приклад покаже два методи програмного додавання наступних обмежень так само, як якщо б це було зроблено у Interface Builder:

Ширина та висота

введіть тут опис зображення

Центр у контейнері

введіть тут опис зображення

Код таблички

override func viewDidLoad() {
    super.viewDidLoad()

    // set up the view
    let myView = UIView()
    myView.backgroundColor = UIColor.blue
    myView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(myView)

    // Add constraints code here (choose one of the methods below)
    // ...
}

Спосіб 1: Якірний стиль

// width and height
myView.widthAnchor.constraint(equalToConstant: 200).isActive = true
myView.heightAnchor.constraint(equalToConstant: 100).isActive = true

// center in container
myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

Спосіб 2: Стиль NSLayoutConstraint

// width and height
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true

// center in container
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true

Примітки

  • Стиль прив'язки є кращим методом порівняно зі NSLayoutConstraintСтилем, однак він доступний лише з iOS 9, тому, якщо ви підтримуєте iOS 8, вам все одно слід використовувати NSLayoutConstraintStyle.
  • Див. Також документацію щодо програмного створення обмежень .
  • Дивіться цю відповідь для подібного прикладу додавання обмеження закріплення.

5

Що стосується вашого другого питання про властивості, ви можете використовувати його, self.myViewлише якщо ви оголосили його як властивість у класі. Оскільки myViewце локальна змінна, ви не можете використовувати її таким чином. Для отримання більш детальної інформації з цього питання , я б порекомендував вам пройти через документацію яблука на декларованих властивості ,


5

чому я не можу використовувати властивість like self.myViewзамість локальної змінної типу myView?

спробуйте використовувати:

NSDictionaryOfVariableBindings(_view)

замість self.view


Через це моє додаток аварійно завершує роботу, і з’являється повідомлення: „Неможливо проаналізувати формат обмеження: polylineImageView не є ключем у словнику переглядів“.
Тай Ле

4

Також зауважте, що з iOS9 ми можемо програмно визначати обмеження "більш стислими та легшими для читання", використовуючи підкласи нового допоміжного класу NSLayoutAnchor .

Приклад з документа:

[self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.