Подтвердить что ты не робот

Могу ли я использовать автозапуск, чтобы обеспечить различные ограничения для пейзажной и портретной ориентации?

Можно ли изменить ограничения при повороте устройства? Как это может быть достигнуто?

Простым примером может быть два изображения, которые в портрете складываются один над другим, но в ландшафте бок о бок.

Если это невозможно, как еще я могу выполнить этот макет?

Я создаю свои представления и ограничения в коде и не использую конструктор интерфейса.

4b9b3361

Ответ 1

Изменить: Используя новую концепцию класса размеров, представленную в Xcode 6, вы можете легко настроить различные ограничения для определенных классов размера в Interface Builder. Большинство устройств (например, все текущие iPhone) имеют компактный вертикальный размерный класс в ландшафтном режиме.

Это гораздо лучшее понятие для общих решений макета, чем определение ориентации устройства.

При этом, если вам действительно нужно знать ориентацию, UIDevice.currentDevice().orientation - это путь.


Оригинальное сообщение:

Переопределите метод updateViewConstraints UIViewController, чтобы предоставить ограничения компоновки для конкретных ситуаций. Таким образом, макет всегда настраивается в соответствии с ситуацией. Убедитесь, что они образуют полный набор ограничений с созданными в раскадровке. Вы можете использовать IB для настройки своих общих ограничений и пометить тех, кто будет изменен, чтобы быть удаленными во время выполнения.

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

-(void)updateViewConstraints {
    [super updateViewConstraints];

    // constraints for portrait orientation
    // use a property to change a constraint constant and/or create constraints programmatically, e.g.:
    if (!self.layoutConstraintsPortrait) {
        UIView *image1 = self.image1;
        UIView *image2 = self.image2;
        self.layoutConstraintsPortrait = [[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy];
        [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem: image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }

    // constraints for landscape orientation
    // make sure they don't conflict with and complement the existing constraints
    if (!self.layoutConstraintsLandscape) {
        UIView *image1 = self.image1;
        UIView *image2 = self.image2;
        self.layoutConstraintsLandscape = [[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy];
        [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem: image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    }

    BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);
    [self.view removeConstraints:isPortrait ? self.layoutConstraintsLandscape : self.layoutConstraintsPortrait];
    [self.view addConstraints:isPortrait ? self.layoutConstraintsPortrait : self.layoutConstraintsLandscape];        
}

Теперь все, что вам нужно сделать, это инициировать обновление ограничений всякий раз, когда ситуация меняется. Переопределить willAnimateRotationToInterfaceOrientation:duration: для анимации обновления ограничения при изменении ориентации:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    [self.view setNeedsUpdateConstraints];

}

Ответ 2

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

Чтобы избежать предупреждений адреналина, я помещаю все один набор с приоритетом 999, так что он не везде отображается красным.

Затем я добавляю все ограничения в выходные коллекции:

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *portraitConstraints;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *landscapeConstraints;

Наконец, я реализую свой метод ViewControllers viewWillLayout:

- (void) viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    for (NSLayoutConstraint *constraint in self.portraitConstraints) {
        constraint.active = (UIApplication.sharedApplication.statusBarOrientation == UIDeviceOrientationPortrait);
    }
    for (NSLayoutConstraint *constraint in self.landscapeConstraints) {
        constraint.active = (UIApplication.sharedApplication.statusBarOrientation != UIDeviceOrientationPortrait);
    }
}

Это похоже на работу. Я действительно желаю, чтобы вы могли установить активное свойство по умолчанию в редакторе раскадровки.

Ответ 3

Я придерживаюсь того же подхода, что и ваш (без файлов nib или раскадровки). Вы должны обновить свои ограничения в методе updateViewConstraints (путем проверки ориентации устройства). Нет необходимости вызывать setNeedsUpdateConstraints в updateViewConstraints, потому что как только вы меняете ориентацию устройства, последний метод вызывается автоматически.

Ответ 4

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

Я сделал это, сделав мои ограничения в xib для первоначального представления, назначив их выходным точкам в контроллере представления. При повороте я создаю альтернативные ограничения, удаляю розетки, но сохраняю их, вставляю альтернативы.

Отмените процесс при повороте назад.

Ответ 5

Моя идея - обрабатывать ориентацию, изменяя приоритеты ограничений.
Предполагаемые приоритеты будут:

  • пейзаж: 910 активных /10 неактивных.
  • портрет: 920 активных /20 неактивных.

Шаг 1: Создайте ландшафтный (или портретный) дизайн в Раскадке с ограничениями.
Шаг 2: Для ограничений, которые должны быть активны только для режима ландшафтного режима, установите приоритет на 10.
Шаг 3: Добавьте ограничения для портретного режима и установите их приоритет на 920.

В willAnimateRotationToInterfaceOrientation добавить код:

for (NSLayoutConstraint *constraint in myView.constraints) {
    if (UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation)) {
        if (constraint.priority == 10)  constraint.priority = 910;
        if (constraint.priority == 920) constraint.priority = 20;
    } else {
        if (constraint.priority == 20)  constraint.priority = 920;
        if (constraint.priority == 910) constraint.priority = 10;
    }
}

Преимущество этого подхода - легкая настройка в Interface Builder. Когда нам нужно переключиться на любую ориентацию, мы выбираем все ограничения по приоритету и одновременно меняем их (910- > 10, 20- > 920):

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

Интерфейс будет автоматически восстановлен.