tabBarController и navigationControllers в ландшафтном режиме, эпизод II
У меня есть UITabBarController, и каждая вкладка обрабатывает свой UIViewController, который по мере необходимости помещает в стек новые контроллеры. В двух из этих вкладок мне нужно, когда достигается определенный контроллер, возможность вращать iPhone и визуализировать вид в ландшафтном режиме. После долгих попыток я обнаружил, что UITabBarController является обязательным, чтобы переопределить mustAutorotateToInterfaceOrientation. Однако, если я просто возвращаю YES в реализации, возникает следующий нежелательный побочный эффект:
каждый контроллер на каждой вкладке автоматически переводится в альбомный режим при повороте iPhone.
Даже переопределение ifAutorotateToInterfaceOrientation в каждом контроллере для возврата NO не работает: при повороте iPhone контроллер переводится в альбомный режим.
Я реализовал shouldAutorotateToInterfaceOrientation следующим образом в подклассе UITabBarController:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if([self selectedIndex] == 0 || [self selectedIndex] == 3)
return YES;
return NO;
}
Так что только две вкладки, которые меня интересуют, фактически получают поддержку ландшафтного режима. Есть ли способ поддержки ландшафтного режима для конкретного контроллера в стеке конкретной вкладки?
Я безуспешно пытался что-то вроде
(BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation {
if([self selectedIndex] == 0 || [self selectedIndex] == 3)
{
if ([[self selectedViewController] isKindOfClass: [landscapeModeViewController class]])
return YES;
}
return NO;
}
Кроме того, я попытался с помощью метода делегата didSelectViewController, но безуспешно. Любая помощь с благодарностью. Спасибо.
7 ответов
Это сработало для меня:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(self.selectedIndex == 0 && [[[self.viewControllers objectAtIndex:0] visibleViewController] isKindOfClass:[MyViewController class]])
return YES;
else
return NO;
}
Вот расширение UITabBarController, которое делегирует вызовы shouldAutorotateToInterfaceOrientation
на текущий выбранный дочерний контроллер. Используя это расширение, вам больше не нужно создавать подкласс UITabBarController, и вы можете использовать shouldAutorotateToInterfaceOrientation
в ваших контроллерах, как и следовало ожидать.
UITabBarController + Autorotate.h:
#import <UIKit/UIKit.h>
@interface UITabBarController (Autorotate)
@end
UITabBarController + Autorotate.m:
#import "UITabBarController+Autorotate.h"
@implementation UITabBarController (Autorotate)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
UIViewController *controller = self.selectedViewController;
if ([controller isKindOfClass:[UINavigationController class]])
controller = [(UINavigationController *)controller visibleViewController];
return [controller shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
@end
Я смог использовать это некоторое время (из контроллера панели вкладок моего приложения) без проблем:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
Таким образом, в соответствующем VC мы получаем реальную проверку, в данном случае для просмотра фотогалереи (что еще?):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
Мое представление галереи даже не на вершине стека для данного Nav Controller. Это все еще называют.
Увы, я только что обнаружил, что это не так хорошо работает, когда VC скрывается внутри MoreViewController (в отличие от четырех основных вкладок). В этом случае моя галерея VC никогда не вызывается. Я думаю, это потому, что ВК, которому я все время звонил, на самом деле является навигационным контроллером из выбранной вкладки, который затем передает информацию в соответствующий ВК, в данном случае в мою фотогалерею ВК. Но для More VC все работает не так хорошо... ааа, и оттуда все идет по кругу вниз.:\
Я пытался использовать модификации Андреаса (см. В другом месте в этой теме), но безрезультатно. Подсказки приветствуются!
Я столкнулся с теми же проблемами, что и вы, работая с UITabBarController. Мне нужно было контролировать, какие UIViewControllers было разрешено вращать, а какие нет. Моя главная проблема была с вкладкой БОЛЬШЕ. Я не хотел, чтобы какой-либо из контроллеров UIViewControllers, включенных во вкладку MORE, вращался.
Моим решением было создать свой собственный UITabBarController, который я назвал MyTabBarController:
@interface MyTabBarController : UITabBarController <UITabBarDelegate> {
}
Затем я реализовал метод shouldAutorotateToInterfaceOrientation:
@implementation MyTabBarController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
UIViewController *controller = [self selectedViewController];
if ((controller == [self moreNavigationController]) || ([self selectedIndex] == 4))
{
return interfaceOrientation == UIInterfaceOrientationPortrait;
}
return [controller shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
@end
Мне нужно было узнать, была ли выбрана вкладка БОЛЬШЕ. Это двухступенчатый процесс; когда изначально выбрана вкладка MORE, API возвращает selectedIndex выше 4, поэтому мне нужно было сравнить выбранный контроллер с moreNavigationController.
Если UIViewController выбран из вкладки MORE, то selectedIndex наконец равен 4, но selectedController больше не является moreNavigationController, а выбранным UIViewController.
If ((controller == [self moreNavigationController]) || ([self selectedIndex] == 4)) решает эту проблему.
Теперь, когда я запускаю свое приложение, мои UIViewControllers на вкладке БОЛЬШЕ не поворачиваются. Я надеюсь, что это поможет другим разработчикам, которые сталкиваются с теми же проблемами, что и я.
Эмилио
Из того, что я видел здесь и в других местах, я соединил решение, которое использует метод shouldAutorotate
со старого shouldAutorotateToInterfaceOrientation
был объявлен устаревшим
Я поместил его в категорию для UITabBarController. Я так надеюсь, что это допустимо!
// call to method shouldAutorotate replaces call to method shouldAutorotateToInterfaceOrientation (deprecated)
-(BOOL)shouldAutorotate
{ // check whether selected view controller should autorotate
UIViewController *controller = self.selectedViewController;
if ([controller isKindOfClass:[UINavigationController class]])
{ // in case it is a navigation controller: get visible view of that
controller = [(UINavigationController *)controller visibleViewController];
}
return [controller shouldAutorotate];
}
Спасибо Спасибо спасибо. Это было 2 дня, чтобы выяснить, как это сделать. Вот мое мнение о вашей большой помощи, когда у вас есть tabBarController с навигационными контроллерами.
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation {
UIViewController *controller = self.selectedViewController;
if ([controller isKindOfClass:[UINavigationController class]])
controller = [(UINavigationController *)controller visibleViewController];
if([controller isKindOfClass:[LOCviewcontroller class]])
return YES;
else
if([controller isKindOfClass:[personWebSiteView class]])
return YES;
else return NO;
}
Любая критика кода неофитного кодера всегда ценится... Джек
Это действительно нормально для подкласса UITabBarController (как предложено в принятом ответе выше)?
Я понял, что Apple говорит что-то вроде: "Вы никогда не должны создавать подкласс UITabBarController или UINavigationController" - или я неправильно понял?
Тем не мение; Я нашел этот учебник, где они подклассы UIViewController, в котором они помещают UITabBarController.