Мое приложение имеет приблизительно 10 различных UIViewControllers, только один из которых я хочу переключиться на альбомный режим, если устройство повернуто. (Все остальные, я хочу сохранить в портрете.)
Для реализации вращения на том одном представлении я должен был реализовать 'shouldAutorotate' метод его контроллера и возвратить ДА. Так как к этому представлению получают доступ через контроллер навигации, я также должен был создать подкласс UINavigationController, который реализует 'shouldAutorotate', и возвратите ДА.
Это решение работы, но слишком хорошо. Я нахожу, что все UIViewControllers, которые я продвигаю на свой подкласс UINavigationController, отвечают на вращение, даже если я реализую 'shouldAutorotate' и возвращаюсь НЕТ. (Помните: Я только хочу, чтобы один конкретный UIViewController ответил на вращение, не всех в стопке контроллера навигации.)
Так, мой вопрос: как я лучше всего делаю это? Все решения, которые я могу предложить, кажутся 2) 1) громоздкий и 2) хуже, кажись, не работать.
Большое спасибо.
Я видел примеры того, как вы это делаете, но не мог заставить его работать должным образом. Я нашел лучший способ сделать это на примерах Apple. В основном вы реализуете PresentModalViewController и создаете другое представление. UIKit выполняет базовую анимацию вращения и исчезает между видами. Вы должны реализовать повернутое представление как класс делегата, чтобы он мог вернуться к своему вызывающему классу, чтобы отклонить его и обновить ориентацию.
- (void)orientationChanged:(NSNotification *)notification
{
// We must add a delay here, otherwise we'll swap in the new view
// too quickly and we'll get an animation glitch
NSLog(@"orientationChanged");
[self performSelector:@selector(updateLandscapeView) withObject:nil afterDelay:0];
}
А затем для отображения экрана в альбомной ориентации:
- (void)updateLandscapeView
{
PortraitView *portraitView = [[PortraitView alloc] init];
portraitView.delegate = self;
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
{
[self presentModalViewController: portraitView animated:YES];
isShowingLandscapeView = YES;
}
else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
{
[self dismissModalViewControllerAnimated:YES];
isShowingLandscapeView = NO;
}
[portraitView release];
}
Я делаю это, имея корневой контроллер представления (это может быть UITabBarController), и в его методе viewDidLoad я подписываюсь на события вращения:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didRotate:)
name:@"UIDeviceOrientationDidChangeNotification"
object:nil];
Затем в методе didRotate: я смотрю, какой Контроллер представления виден, когда произошло вращение, и в какой ориентации находится телефон:
- (void) didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
/*
DEVICE JUST ROTATED TO PORTRAIT MODE
orientation == UIDeviceOrientationFaceUp ||
orientation == UIDeviceOrientationFaceDown
*/
if(orientation == UIDeviceOrientationPortrait) {
/*
DEVICE JUST ROTATED TO LANDSCAPE MODE
*/
}else if(orientation == UIInterfaceOrientationLandscapeLeft ||
orientation == UIInterfaceOrientationLandscapeRight) {
}
}
Внутри этого didRotate: вы можете посмотреть, какой является видимым viewController, и делать оттуда то, что вы хотите.
Я представляю контроллер модального представления в ландшафтном режиме, когда виден конкретный контроллер представления, а телефон повернут в альбомную ориентацию. Если виден какой-либо другой контроллер представления, я игнорирую событие.
Я заставляю мой модальный контроллер представления отображать альбомный режим в его методе viewWillAppear - я могу передать этот код кому угодно, если он этого захочет.
Надеюсь, это поможет.
Дэйв