tabBarController и NavigationControllers в ландшафтном режиме, эпизод II
-
09-09-2019 - |
Вопрос
У меня есть UITabBarController, и каждая вкладка обрабатывает отдельный UIViewController, который по мере необходимости добавляет в стек новые контроллеры.В двух из этих вкладок мне нужна при достижении определенного контроллера возможность поворачивать iPhone и визуализировать вид в ландшафтном режиме.После долгих усилий я обнаружил, что для переопределения mustAutorotateToInterfaceOrientation необходимо создать подкласс UITabBarController.Однако, если я просто верну YES в реализации, возникает следующий нежелательный побочный эффект:
каждый контроллер на каждой вкладке автоматически переводится в альбомный режим при повороте iPhone.
Даже переопределение mustAutorotateToInterfaceOrientation в каждом контроллере для возврата NO не работает:когда iPhone поворачивается, контроллер переходит в ландшафтный режим.
Я реализовал mustAutorotateToInterfaceOrientation следующим образом в подклассе 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.Любая помощь очень ценится.Спасибо.
Решение
Это сработало для меня:
- (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+Автоповорот.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);
}
Представление моей галереи даже не находится на вершине стека для данного контроллера навигации.Его все равно вызывают.
Увы, я только что обнаружил, что это не делает так хорошо работают, когда венчурный капиталист скрывается внутри ПодробнееViewController (в отличие от четырех основных вкладок).В этом случае в мою галерею VC никогда не позвонят.Я думаю, это потому, что виртуальный компьютер, которому я все это время звонил, на самом деле является навигационным контроллером выбранной вкладки, который затем передает информацию в соответствующий виртуальный компьютер, в данном случае в мою фотогалерею в виртуальный компьютер.А вот у More VC дела обстоят не так радужно...иииии, дальше дела идут под откос.:\
Я пробовал использовать модификации Андреаса (см. другие разделы этой темы), но безрезультатно.Подсказки приветствуются!
Я столкнулся с теми же проблемами, что и вы, при работе с UITabBarController.Мне нужно было контролировать, каким UIViewControllerм разрешено вращаться, а каким нет.Моя основная проблема была с вкладкой БОЛЬШЕ.Я не хотел, чтобы какой-либо из UIViewControllers, включенных в вкладку «БОЛЬШЕ», вращался.
Моим решением было создать собственный UITabBarController, который я назвал MyTabBarController:
@interface MyTabBarController : UITabBarController <UITabBarDelegate> {
}
Затем я реализовал метод mustAutorotateToInterfaceOrientation:
@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
Мне нужно было узнать, выбрана ли вкладка «БОЛЬШЕ».Это двухэтапный процесс;когда изначально выбрана вкладка «БОЛЬШЕ», 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.