2

UPDATE 2Ограничить вращение в Tab Bar View Controllers

В моем UITabBarController подклассу я попытался добавить это:

-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { 

     NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; 
     [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 

} 

Теперь, каждый раз, когда я выбираю вкладку элемент, устройство поворачивается в портретный режим отлично , Однако теперь я могу повернуть устройство, пока выбрано (a), и устройство будет вращаться в альбомном режиме. Как я могу остановить вращение устройства?

Я считаю, что этот метод в моем закладке контроллера подкласса, что является причиной этого:

- (BOOL)shouldAutorotate { 

    if(self.selectedIndex == 0) 
    { 
     return NO; 
    } 

    return [self.viewControllers.lastObject shouldAutorotate]; 
} 

Если я вернусь «NO» Я не могу повернуть, когда я нахожусь в контроллере представления, но когда я выбираю его, он автоматически не поворачивается к портрету. Если я вернусь «ДА», я могу повернуть, когда я нахожусь в контроллере представления, но когда я его выбираю, он автоматически поворачивается на портрет.


У меня есть обычай Tab Bar Controller в моем приложении с помощью следующей иерархии:

UITabBarController 
    | 
    UINavigationController 
    | | 
    | UIViewController(a) 
    | 
    UINavigationController 
    | | 
    | UIViewController(b) 
    | 
    UINavigationController 
     | 
     UIViewController(c) 

Я хочу View Controller (а) только иметь возможность просматривать в портретном режиме, а также View контроллеры (b) и (c) для просмотра во всех направлениях, но вверх ногами. Теперь я могу сделать это с каждым контроллером представления отдельно, но моя проблема возникает, когда я нахожусь в (b) в ландшафтном режиме и выбираю элемент табуляции для (a), а затем отображается в ландшафтном режиме, который не выглядит хорошо. Как я могу убедиться, что панель вкладок (или контроллер вида) проверяет, можно ли просматривать текущий контроллер просмотра в текущей ориентации?

В случае необходимости, вот мой код (а), что ограничивает его в портретный режим сам по себе:

- (BOOL) shouldAutorotate 
{ 
    return NO; 
} 

- (NSUInteger) supportedInterfaceOrientations 
{ 
    return UIInterfaceOrientationMaskPortrait; 
} 

UPDATE

Я добавил это, чтобы посмотреть контроллер (а), но я получаю черный квадрат в середине моего представления, а заголовок в панели навигации больше не центрирован.

-(void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 


    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; 
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 


} 

ответ

4

С прошивкой 7.0 UITabBarController поддерживает пересылку ориентации с помощью - (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController.

Он отлично работает, пока вы не перейдете на другую вкладку, находясь в ориентации интерфейса, которую эта конкретная вкладка не поддерживает.

К сожалению, контроллер таблеток не заставляет вращение в этом случае, и единственный способ - использовать частный API.

Примечание: Я использую attemptRotationToDeviceOrientation для поворота интерфейса к ориентации устройства при переключении с вкладки «Только портрет» на вкладку, которая поддерживает любую ориентацию.

Это мой подход к проблеме:

static const NSInteger kPortraitOnlyTabIndex = 1; 

@interface TabBarController : UITabBarController<UITabBarControllerDelegate> 
@end 

@implementation TabBarController 

- (id)initWithCoder:(NSCoder *)aDecoder { 
    if(self = [super initWithCoder:aDecoder]) { 
     self.delegate = self; 
    } 
    return self; 
} 

- (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController { 
    if(tabBarController.selectedIndex == kPortraitOnlyTabIndex) { 
     return UIInterfaceOrientationMaskPortrait; 
    } 

    return UIInterfaceOrientationMaskAllButUpsideDown; 
} 

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { 
    [UIViewController attemptRotationToDeviceOrientation]; 

    if([self.viewControllers indexOfObject:viewController] == kPortraitOnlyTabIndex) { 
     SEL sel = NSSelectorFromString(@"setOrientation:"); 
     if([[UIDevice currentDevice] respondsToSelector:sel]) { 
#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Warc-performSelector-leaks" 
      [[UIDevice currentDevice] performSelector:sel withObject:(__bridge id)((void*)UIInterfaceOrientationPortrait)]; 
#pragma clang diagnostic pop 
     } 
    } 
} 

@end 

Я ставлю пример приложения на Github в https://github.com/pronebird/TabBarOrientationExample

+0

Благодарим вас за ответ, но это не отвечает на мой вопрос. – Jacob

+0

@ Jacob, каким образом он не отвечает на ваш вопрос? Вы используете неправильное перечисление, переключитесь вправо. – Andy

+0

Я не вижу, как изменение моего типа возврата в одном контроллере просмотра влияет на вращение в другом, когда оно выбрано в контроллере табуляции. – Jacob

0

Его простой, Создать подкласс UITabBarController, и реализовать метод делегата

- (BOOL)tabBarController:(UITabBarController *)tbController shouldSelectViewController:(UIViewController *)viewController { 
    //Check for orientation here 
    if (supported orientation for view controller == [[UIApplication sharedApplication] statusBarOrientation]) { 
     return YES; 
    } else { 
     return NO; 
    } 
} 
+0

Это не позволит пользователю выбрать вкладку все же. Есть ли способ проверить ориентацию, повернуть устройство, если текущая ориентация не поддерживается, не может затем вернуться да? – Jacob

1

Я использовал обходной путь один раз для этой конкретной проблемы. Идея заключалась в подклассе UITabBarController и установила его delegate. Затем в подклассе я сделал следующий «взлом»: когда был выбран контроллер только для портрета, я нажал и немедленно отклонил пустой модальный VC. Это заставило iOS установить правильную ориентацию.

-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { 
    UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation; 
    NSInteger currentViewControllerSupportsLandscape = ([viewController supportedInterfaceOrientations] & UIInterfaceOrientationMaskLandscape); 
    if(UIInterfaceOrientationIsLandscape(currentOrientation) && !currentViewControllerSupportsLandscape) { 
     //workaround to force rotating to portrait 
     UIViewController *c = [[UIViewController alloc]init]; 
     [viewController presentViewController:c animated:NO completion:nil]; 
     [viewController dismissViewControllerAnimated:NO completion:nil]; 
    } 
} 

Обратите внимание, что это, вероятно, зависит от некоторых деталей реализации и может прекратить работу в будущем.

EDIT: Вы также должны реализовать supportedInterfaceOrientations и shouldAutorotate в подклассе UITabBarController. И вы должны вернуть YES в -shouldAutorotate в диспетчере вида, которым хотите оставаться на портрете. В противном случае он не будет вращаться от пейзажа к портрету, если он выбран на панели вкладок.

- (NSUInteger) supportedInterfaceOrientations { 
    return [self.currentViewController supportedInterfaceOrientations]; 

} 

- (BOOL) shouldAutorotate { 
    return [self.currentViewController shouldAutorotate]; 
} 

- (UIViewController*) currentViewController { 
    UIViewController* controller = self.selectedViewController; 
    if([controller isKindOfClass:[UINavigationController class]]) { 
     controller = [((UINavigationController*)controller).viewControllers objectAtIndex:0]; 
    } 
    return controller; 
} 
+0

Это не работает для меня, только строка состояния поворачивается в положение портрета ... – Jacob

+0

Возможно, это потому, что вы возвращаете 'NO' в' shouldAutorotate'. Посмотрите на отредактированный ответ. –

+0

Как я уже сказал в моем отредактированном вопросе, если я вернусь ДА в shouldAutorotate, я могу просто повернуть устройство, пока выбран контроллер просмотра, и он будет вращаться в ландшафтном режиме, а не строго оставаться в портрете. – Jacob