Могу ли я использовать setFrame и autolayout в одном представлении?

Я хочу добавить отступы ко всем моим кнопкам, поэтому я подклассифицировал UIButton, и среди других изменений я хотел добавить фиксированный отступ с помощью метода setFrame. Все работало, кроме setFrame. Я проверил все вокруг и обнаружил, что если я сниму флажок "использование AutoLayout" в этом представлении, то я могу использовать setFrame, и это работает. Это можно обойти? Я действительно хочу использовать autolayout, потому что это помогает сделать приложение красивым как на iphone 5, так и на более ранних устройствах. Но я также хотел бы использовать setFrame в моем подклассе, чтобы облегчить мою жизнь.

Подводя итоги, я задаюсь вопросом: могу ли я использовать автоматическую разметку, а также программно настроить рамку UIView?

5 ответов

Решение

Да, это можно сделать.

Если вы установите вид translatesAutoresizingMaskIntoConstraints = YES затем звонит setFrame: автоматически переводятся во время выполнения в ограничения макета на основе текущего представления autoresizingMask, Это позволяет смешивать макет на основе фреймов с макетом на основе ограничений.

Например, вы можете использовать Auto Layout для определения макета всех подпредставлений представления, но при этом вызывать setFrame: установить размер и положение самого представления. С вашей точки зрения, вы делаете макет со смесью Auto Layout и прямой манипуляции с кадром. Но система на самом деле использует ограничения для обработки всего.

Тем не менее, есть одна большая оговорка об использовании translatesAutoresizingMaskIntoConstraints,

Когда вы делаете это, вам все равно нужно убедиться, что эти автоматические ограничения могут быть удовлетворены с остальными вашими ограничениями.

Так, например, предположим, что уже есть ограничения, которые определяют размер и положение вашего представления, а затем вы также установите translatesAutoresizingMaskIntoConstraints = YES и называется setFrame:, Призыв к setFrame: создаст новые ограничения для представления, которые, вероятно, будут конфликтовать с уже существующими ограничениями.

(На самом деле, эта ошибка происходит часто. Если вы когда-либо видите сообщение журнала, жалующееся на конфликтующие ограничения, и одним из этих ограничений является NSAutoresizingMaskLayoutConstraint то, что вы видите, это конфликт с автоматическим ограничением. Это легкая ошибка, потому что translatesAutoresizingMaskIntoConstraints = YES является значением по умолчанию, поэтому, если вы настраиваете ограничения в коде, вы должны помнить, чтобы отключить его, если вы не хотите эти автоматические ограничения.)

Напротив, предположим еще раз, что уже существуют ограничения, которые определяют размер и положение вашего представления, но затем вы устанавливаете translatesAutoresizingMaskIntoConstraints = NO прежде чем позвонить setFrame:, В этом случае ваш setFrame: вызовы не создают новых ограничений, поэтому между отдельными ограничениями не будет конфликта. Однако в этом случае все еще существует "конфликт" между ограничениями и установленным значением кадра. При следующем вызове Auto Layout он увидит уже существующие ограничения в представлении, вычислит требуемое им значение кадра и установит для самого кадра требуемое значение, перекрывая значение, заданное вами вручную.

Для получения более подробной информации, ознакомьтесь с разделом "Принятие автоматической разметки" в Руководстве Apple по автоматической разметке какао.

Что оказалось самым простым для меня, так это удалить представление, которое я хотел переместить / изменить размер, из его суперпредставления, установить его frame, а затем добавить его обратно. Например, взять кастом UILabel в UITableViewCell подкласс:

[cell.myLabel removeFromSuperview];
cell.myLabel.frame = someFrameIGenerated;
[cell.contentView addSubview:cell.myLabel];

Что-то, что работало для меня, просто добавляло IBOutlet для моих ограничений к контроллеру представления, затем изменяя constant недвижимость на выходе.

Например, чтобы изменить происхождение x представления, установите выход из ведущего ограничения этого представления на свой контроллер. Другими словами, создать выход @IBOutlet var labelXOrigin: NSLayoutConstraint!, Затем, когда вы хотите отрегулировать положение х, просто сделайте что-то вроде

self.labelXOrigin.constant = 20.0 // Or whatever origin you want to set.

Лучший способ установить фрейм подвида - это метод viewWillLayoutSubviews в проектах autolayout.

set property translationAutoresizingMaskIntoConstraints = true это будет работать после того, как представление появилось или вкладка на кнопке для установки сразу после появления представления.

Если ваше приложение не поддерживает несколько ориентаций устройств.

В viewDidLoad установите кадр вида, размер которого вы хотите изменить.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [aView setFrame:CGRectMake(15, 15, 100, 100)];
}

Затем в viewDidLayoutSubviews:

-(void)viewDidLayoutSubviews
{
    [self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
}

Я не уверен, но я думаю, что если вы используете это решение, переключение одной ориентации на другую может вызвать проблемы

Другие вопросы по тегам