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

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

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

Ответ 1

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

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

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

Однако существует одна большая оговорка об использовании translatesAutoresizingMaskIntoConstraints.

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

Лучший способ установить фрейм подзадача - метод viewWillLayoutSubviews в проекты автоопределения.

установить свойство translautAutoresizingMaskIntoConstraints = true this будет работать после того, как будет отображаться представление или кнопка на кнопке для установки, сразу после вид.

Ответ 5

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

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

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