Я знаю, что многие люди уже задавали массу вопросов по этому поводу, но даже с ответами я не могу заставить это работать.
Когда я имею дело с ограничениями на раскадровке, это легко, но с кодом мне трудно. Я пытаюсь, например, иметь представление, которое остается с правой стороны и имеет высоту экрана в соответствии с ориентацией экрана. Это мой код:
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
вместо локальной переменной типа myView
?
objective-c
ios
constraints
autolayout
Pierre23
источник
источник
myView
? (3) Чтоvivi
(как спросил ACB)? (4) Есть ли у васmyView
заявленная недвижимостьself
?Ответы:
При использовании Auto Layout в коде установка рамки ничего не делает. Таким образом, тот факт, что вы указали ширину 200 в представлении выше, ничего не значит, когда вы устанавливаете для него ограничения. Чтобы набор ограничений представления был однозначным, ему нужны четыре вещи: позиция по оси x, позиция по оси y, ширина и высота для любого заданного состояния.
В настоящее время в приведенном выше коде у вас есть только два (высота относительно супервизора и y-позиция относительно супервизора). В дополнение к этому у вас есть два обязательных ограничения, которые могут конфликтовать в зависимости от того, как установлены ограничения супервизора представления. Если суперпредставление должно иметь обязательное ограничение, указывающее, что его высота будет некоторым значением меньше 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)]];
Устное описание этого макета звучит следующим образом, начиная с ограничения по вертикали:
Если вы просто хотите, чтобы представление заполняло всю высоту супервизора без ограничения высоты супервизора, то вы просто опустите
(>=748)
параметр в тексте визуального формата. Если вы считаете, что(>=748)
параметр необходим для присвоения ему высоты - в данном случае вы этого не делаете: закрепляя представление на краях супервизора с помощью синтаксиса bar (|
) или bar с пробелом (|-
,-|
), вы даете своему представлению y -position (закрепление вида на одном краю) и y-положение с высотой (закрепление вида на обоих краях), таким образом удовлетворяя ваши ограничения, установленные для вида.Что касается вашего второго вопроса:
Используя
NSDictionaryOfVariableBindings(self.myView)
(если у вас была настройка свойств для myView) и вводя это в ваш VFL для использованияself.myView
в вашем тексте VFL, вы, вероятно, получите исключение, когда autolayout попытается проанализировать ваш текст VFL. Это связано с точечной нотацией в ключах словаря и системой, которую пытается использоватьvalueForKeyPath:
. См. Здесь аналогичный вопрос и ответ .источник
Привет, я много использую эту страницу для поиска ограничений и «как». Мне потребовалась целая вечность, чтобы понять, что мне нужно:
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)]];
источник
Свифт версия
Обновлено для Swift 3
В этом примере будут показаны два метода для программного добавления следующих ограничений так же, как если бы это было сделано в Интерфейсном Разработчике:
Ширина и высота
Центр в контейнере
Код шаблона
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, вам все равно следует использоватьNSLayoutConstraint
стиль.источник
Что касается вашего второго вопроса о свойствах, вы можете использовать,
self.myView
только если вы объявили его как свойство в классе. ПосколькуmyView
это локальная переменная, вы не можете использовать ее таким образом. Чтобы получить более подробную информацию об этом, я бы порекомендовал вам просмотреть документацию Apple по объявленным свойствам ,источник
почему я не могу использовать свойство, например,
self.myView
вместо локальной переменной, например myView?попробуйте использовать:
NSDictionaryOfVariableBindings(_view)
вместо
self.view
источник
Также обратите внимание, что в iOS9 мы можем программно определять ограничения «более кратко и легче для чтения», используя подклассы нового вспомогательного класса NSLayoutAnchor .
Пример из документа:
[self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;
источник