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

Как обрабатывать различные ориентации в iOS

ДОБАВЛЕНО: Вы можете получить доступ к этому проекту на github ios6rotations


Извините, ребята, что задали вопрос о вращении экрана в iOS 6, но это действительно боль в заднице. И я все еще не могу понять это полностью - по некоторым причинам он ведет себя по-разному при определенных обстоятельствах.

У меня есть следующая простая иерархия представлений в моем тестовом приложении:

То, что я пытаюсь достичь, - сохранить синий контроллер только в ландшафтном режиме, а красный - только в портретном.

У меня есть подкласс UINavigationController с таким кодом внутри:

@implementation CustomNavController

- (BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

- (NSUInteger)supportedInterfaceOrientations
{
    return  [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end

В моем синем контроллере я реализовал это:

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}

И в красном контроллере это:

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

Теперь у меня есть следующее поведение:

  • Приложение запущено в альбомной ориентации (ОК)
  • Когда я нажимаю кнопку, мой красный контроллер тоже нажимает на пейзаж (это не нормально, потому что это должно быть показано в портрете)
  • Он успешно вращается к портрету, но не назад к ландшафту.
  • Если я оставил красный контроллер в режиме "Портрет", мой синий контроллер (который ограничен пейзажем) отображается в режиме "Портрет".

P.S. Все мои методы поворота (выложенные выше) вызываются нормально (кстати, почему эти методы вызывают так много раз при переходе экрана - 5-6 раз)

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation не вызывается с нажатием

Все (кроме PortraitUpsideDown) ориентации включены в plist.

Вопрос: как заставить вращение поддерживать поддерживаемую ориентацию в каждом контроллере?

Я предлагаю вам опубликовать здесь (как ответы) любой 100% рабочий код для обработки поворотов в ios6 (например, если у вас есть для iPad с SplitController) - я сохраню этот вопрос в избранных, чтобы иметь все в одном месте когда мне нужно справляться с определенными ситуациями. Ура!

ДОБАВЛЕНО: Пожалуйста, не публикуйте это как ответ от пейзажа к портрету Я надеюсь, это более элегантный способ сделать это.

4b9b3361

Ответ 1

Использование -[UIDevice setOrientation:] - частный API, и ваше приложение будет отклонено. См. этот вопрос.

То, что вы просите, невозможно с использованием общедоступного API, а также не рекомендуется с точки зрения HIG. Что поддерживается, и вы должны реализовать, это модальная презентация различных контроллеров представлений с различной поддерживаемой ориентацией интерфейса. Вот почему стандартная реализация UINavigationController - это всегда вращать; он предполагает, что все контроллеры представлений имеют одинаковые поддерживаемые ориентации интерфейса.

Возьмем, например, воспроизведение видео на iPhone. Откройте видео приложения (которое поставляется с iOS). Контроллер корневого представления поддерживает только портретную ориентацию. Тем не менее, запустите видео, и появится модальный контроллер просмотра, который поддерживает только ориентацию ландшафтного интерфейса. Это похоже на то, что вы хотите достичь.

Вот почему preferredInterfaceOrientationForPresentation не вызывается. preferredInterfaceOrientationForPresentation вызывается только при использовании presentViewController:animated:.

Небольшая ошибка, если вам требуется панель навигации на каждом этапе вашей сцены, вам нужно будет приложить каждый контроллер модального представления к контроллеру навигации. Затем вы можете передать необходимые данные в prepareForSegue:, обратившись к topViewController объекта навигационного контроллера в сегменте.


Вот пример проекта, который ведет себя правильно в соответствии с вашими требованиями (или, по крайней мере, даст вам идеи, как реализовать):

http://www.mediafire.com/?zw3qesn8w4v66hy

Ответ 2

Стоимость моих двух центов.

Вы можете быстро представить прозрачный вид пустой прозрачный, затем отпустите его, возможно, в ViewDidLoad: или viewWillAppear: в вашем классе ViewController и ViewControllerSecond в качестве быстрого обходного пути.

Кроме того, в раскадровке вы можете настроить ориентацию класса ViewController на ландшафт визуально.

Ответ 3

используйте эту строку для программной смены ориентации... работа 100%

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];

а также при добавлении этой строки в это время появляется одно предупреждение и для удаления этого предупреждения просто добавьте следующий код в файл реализации.. вверху.

@interface UIDevice (MyPrivateNameThatAppleWouldNeverUseGoesHere)
- (void) setOrientation:(UIInterfaceOrientation)orientation;
@end

и после этого в следующем методе просто напишите этот код, если потребуется..

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return your supported orientations

 if (currentMainView==blueOne) {
        return toInterfaceOrientation== UIInterfaceOrientationPortrait;
    }
}

Ответ 4

У меня похожая ситуация в одном из моих приложений (хотя обратите внимание, что я не использую UINavigationController).

Измените методы shouldAutorotate в обоих режимах просмотра:

//in blue (landscape only)
-(BOOL)shouldAutorotate{
    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
        return YES;
    }
    else {
        return NO;
    }
}

//in red (portrait only)
-(BOOL)shouldAutorotate{
    if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {
        //note that UIInterfaceOrientationIsPortrait(self.interfaceOrientation) will return yes for UIInterfaceOrientationPortraitUpsideDown
        return YES;
    }
    else {
        return NO;
    }
}

Сохраняйте методы supportedInterfaceOrientations одинаковыми.

Ответ 5

#pragma mark- Orientation Delegate Method:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{   Orientation = [UIApplication sharedApplication].statusBarOrientation;
    if (Orientation == UIInterfaceOrientationLandscapeLeft || Orientation == UIInterfaceOrientationLandscapeRight)
    {

        // self.scrollView.contentOffset = CGPointMake(self.view.bounds.size.width,1200);

        [scrollView setScrollEnabled:YES];
        [scrollView setContentSize:CGSizeMake(768, 2150)];


    }else if (Orientation == UIInterfaceOrientationPortrait || Orientation == UIInterfaceOrientationPortraitUpsideDown)
    {

        [scrollView setScrollEnabled:YES];
        [scrollView setContentSize:CGSizeMake(768, 1750)];

    }

}

Ответ 6

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

После этой проверки следуя методам,

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

эти изменения в ваших методах помогут вам многое.

Наслаждайтесь программированием!