TabBarController и navigationControllers в ландшафтном режиме, эпизод II
У меня есть UITabBarController, и каждая вкладка обрабатывает другой UIViewController, который при необходимости нажимает на новые контроллеры стека. В двух из этих вкладок мне нужно, когда достигнут определенный контроллер, возможность поворачивать iPhone и визуализировать представление в ландшафтном режиме. После многого боя я обнаружил, что обязательным подклассифицированием UITabBarController является переопределение shouldAutorotateToInterfaceOrientation. Однако, если я просто вернусь ДА в реализации, возникает следующий нежелательный побочный эффект:
каждый контроллер на каждой вкладке автоматически помещается в альбомный режим при повороте iPhone.
Даже переопределение shouldAutorotateToInterfaceOrientation в каждом контроллере для возврата 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 без успеха.
Любая помощь приветствуется.
Спасибо.
Ответы
Ответ 1
Это сработало для меня:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(self.selectedIndex == 0 && [[[self.viewControllers objectAtIndex:0] visibleViewController] isKindOfClass:[MyViewController class]])
return YES;
else
return NO;
}
Ответ 2
Здесь добавляется расширение 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
Ответ 3
Я смог использовать это некоторое время (из моего контроллера панели приложений) без проблем:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
Таким образом, в соответствующем VC мы получим реальную проверку, в этом случае для просмотра фотогалереи (что еще?):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
Моя галерея не даже находится в верхней части стека для данного контроллера Nav. Он по-прежнему вызван.
Увы, я просто обнаружил, что это не работает так хорошо, когда VC скрывается в MoreViewController (в отличие от четырех основных вкладок). В этом случае моя галерея VC никогда не будет вызвана. Я думаю, это потому, что VC, с которым я звонил, на самом деле является навигационным контроллером с выбранной вкладки, который затем распространяет вещи на соответствующий VC, в этом случае моя фотогалерея VC. Но для The More VC все не так хорошо работает... aaaand оттуда идет круговым движением вниз.:\
Я попытался использовать модификации Андреаса (см. в другом месте этой темы), но безрезультатно. Добро пожаловать!
Ответ 4
Я столкнулся с теми же проблемами, что и при работе с UITabBarController. Мне нужно было контролировать, какие UIViewControllers были разрешены для вращения, а какие нет. Моя основная проблема заключалась в закладке MORE. Я не хотел, чтобы любой из 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. Это двухэтапный процесс; когда сначала выбирается вкладка MORE, API возвращает selectIndex выше 4, поэтому мне нужно сравнить выбранный контроллер с moreNavigationController.
Если UIViewController выбран из вкладки MORE, то выбранноеIndex, наконец, 4, но selectedController больше не является большеNavigationController, но выбран UIViewController.
if ((controller == [self moreNavigationController]) || ([self selectedIndex] == 4)) заботится об этой проблеме.
Теперь, когда я запускаю приложение, мои UIViewControllers на вкладке MORE не вращаются. Надеюсь, это поможет другим разработчикам, которые сталкиваются с теми же проблемами, что и я.
Эмилио
Ответ 5
Из того, что я видел здесь и в других местах, я сшил решение, использующее метод 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];
}
Ответ 6
Спасибо, спасибо, спасибо. Это было 2 дня, чтобы выяснить, как это сделать. Здесь я беру на себя всю вашу большую помощь, когда у вас есть tabBarController с navigationControllers.
- (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;
}
Любая критика кода неофитового кодера всегда приветствуется... jack
Ответ 7
Действительно ли это нормально для подкласса UITabBarController (как указано в принятом ответе выше)?
Я понял, что Apple говорит что-то вроде "вы никогда не должны подкласса UITabBarController или UINavigationController" - или я не понял?
В любом случае; Я нашел этот учебник, где они подклассифицируют UIViewController, в который они помещают UITabBarController.