Как обрабатывать различные ориентации в 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) - я сохраню этот вопрос в избранных, чтобы иметь все в одном месте когда мне нужно справляться с определенными ситуациями. Ура!
ДОБАВЛЕНО:
Пожалуйста, не публикуйте это как ответ от пейзажа к портрету Я надеюсь,
это более элегантный способ сделать это.
Ответы
Ответ 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];
}
эти изменения в ваших методах помогут вам многое.
Наслаждайтесь программированием!