13

У меня есть контроллер навигации, который имеет несколько контроллеров представления. Мне нужно поддерживать все ориентации для всех контроллеров представлений, кроме одного специального контроллера, который поддерживает только ландшафт. Этот специальный контроллер просмотра отображается в середине стека навигации. Я провел довольно много исследований, но не нашел хорошего решения. Вот ссылки, которые я прочитал и попробовал.Поддержка ландшафта только для одного вида в UINavigationController

http://www.iphonedevsdk.com/forum/iphone-sdk-development/3219-force-landscape-mode-one-view.html#post60435

How to rotate screen to landscape?

How to autorotate from portrait to landscape mode? iPhone - allow landscape orientation on just one viewcontroller http://goodliffe.blogspot.com/2009/12/iphone-forcing-uiview-to-reorientate.html

Далее я буду пытаться заменить навигационный контроллер с presentModalViewController для того, чтобы отобразить специальный контроллер представления. Затем я собираюсь создать новый контроллер вида навигации в специальном контроллере просмотра, чтобы нажать последующие контроллеры представлений.

Если у кого-то есть лучшая идея, сообщите мне. Очень ценим!

UPDATE: Я успешно использовать метод, который я описал выше: заменить pushViewController с presentModalViewController и создать новый навигационный контроллер.

+0

Вы могли бы поделиться образцом кода? –

ответ

8

Каждого вида помещаемого на навигацию контроллеров суммироваться должны поддерживать одинаковые ориентации. Это означает, что некоторые контроллеры представлений не могут поддерживать только портрет, а другие поддерживают только пейзаж.Другими словами, все контроллеры с видом на той же самой навигационной стека контроллера должен возвращать то же самое в делегат:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

Но есть простое решение этой проблемы! Вот пример перехода от портрета к пейзажу. Вот шаги, чтобы сделать это, а ниже - код для его поддержки.

  1. Создайте «поддельный» контроллер вида, который будет root в контроллере суб-навигации. Этот контроллер просмотра должен поддерживать ландшафт.
  2. Создать новый экземпляр UINavigationController, добавьте экземпляр «фальшивой» контроллер представления в качестве корня и экземпляр контроллера вид ландшафта как второй вид контроллера
  3. Присутствует UINavigationController например, как модальный от контроллера родительского вида

во-первых, создать новый контроллер представления (FakeRootViewController) с этим кодом:

@interface FakeRootViewController : UIViewController 
@property (strong, nonatomic) UINavigationController* parentNavigationController; 
@end 

@implementation FaceRootViewController 
@synthesize parentNavigationController; 
// viewWillAppear is called when we touch the back button on the navigation bar 
(void)viewWillAppear:(BOOL)animated { 
    // Remove our self from modal view though the parent view controller 
    [parentNavigationController dismissModalViewControllerAnimated:YES]; 
} 
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return (interfaceOrientation == UIInterfaceOrientationIsLandscape(interfaceOrientation)); 
} 

Вот код, чтобы представить контроллер представления, что вы хотите показать в ландшафтный режим:

FakeRootViewController* fakeRootViewController = [[FakeRootViewController alloc] init];[fakeRootViewController.navigationItem setBackBarButtonItem:backButton]; // Set back button 
// The parent navigation controller is the one containing the view controllers in portrait mode. 
fakeRootViewController.parentNavigationController = parentNavigationController; 

UINavigationController* subNavigationController = // Initialize this the same way you have initialized your parent navigation controller. 

UIViewController* landscapeViewController = // Initialize the landscape view controller 

[subNavigationController setViewControllers: 
    [NSArray arrayWithObjects:fakeRootViewController, 
               landscapeViewController, nil] animated:NO]; 

[_navigationController presentModalViewController:subNavigationController animated:YES]; 

Помните, что landscapeViewController должен также иметь эту реализацию:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return (interfaceOrientation == UIInterfaceOrientationIsLandscape(interfaceOrientation)); 
} 
+1

+50 amazeballs. – Adam

+0

Наконец, прямой ответ. – Jeef

0

Оно должно быть простым, как внедрение

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

в каждом UIViewController толкнул в вашу UINavigationController. В случае, если один вид UIViewController не должен вращаться, return NO для этой конкретной ориентации в этом конкретном UIViewController. Там есть Гоча здесь, хотя, если ваш UINavigationController реализует

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

он будет блокировать его viewControllers от приема этого метода. В этом случае, вы должны направить сообщение в topViewController с помощью

[[self topViewController] shouldAutorotateToInterfaceOrientation:interfaceOrientation]; 
+3

Я хотел, чтобы все было так просто. Вы пробовали это? Есть несколько проблем с этим. 1. Если вы сделаете особый пейзаж, когда портрет телефона, когда вы поворачиваете телефон в альбомной ориентации, изображение будет неожиданно вращаться к портрету. 2. Когда вы делаете особый пейзаж в первый раз, затем поворачивайте телефон до портрета, затем выходите из специального вида и снова вступаете в силу, просмотр вращается неожиданно. Это похоже на проблему с контроллером навигации, и я действительно хочу, чтобы Apple могла заставить его работать над тем, что вы описали. –

+0

Я пробовал. Я думаю, что проблемы, с которыми вы сталкиваетесь, могут быть специфическими для вашего приложения. Попробуйте запустить новый проект, чтобы изолировать проблему вращения UINavigationController, а затем запустить некоторые эксперименты. – schellsan

0

Вы можете попробовать этот код в UINavigationController для вызова текущего видимого вида по shouldAutorotateToInterfaceOrientation. В моем случае у меня есть UINavigationController в UITabBarController, но вы, вероятно, можете адаптировать его к другим случаям.

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    if ([appDelegate.tabBarController.selectedViewController respondsToSelector:@selector(topViewController)]) 
    { 
     UINavigationController *nc = (UINavigationController*)appDelegate.tabBarController.selectedViewController; 
     return [nc.topViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation]; 
    } 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 
0

Вы можете совершать действия: изменить код с соответствии с schellsan предложения, следующий - Попробуйте добавить currentViewController (который будет толкать к навигации ViewController) в собственности AppDelegate. Когда вы пытаетесь нажать контроллер просмотра, перед этим установите его в контроллер текущего вида. Далее - создайте подкласс rootViewController в контроллере навигации. В этом подклассе методе owerload

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    // Overriden to allow any orientation. 
    return [appDelegate.currentViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation]; 
} 

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

+3

Как вы достигаете того же с версией iOS 6. – Krishnan

1

Там есть частный API, чтобы заставить изменение ориентации. Помещенный в ваш толкнул контроллера вида -viewWillAppear::

if ([UIDevice instancesRespondToSelector:@selector(setOrientation:)]) { 
    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 
} 

Чтобы подавить предупреждение компилятора, добавьте к этому .m файл контроллера представления:

@interface UIDevice() 
- (void)setOrientation:(UIDeviceOrientation)orientation; // private API to let POIEntryVC be pushed over landscape route view 
@end 

Как всегда, есть риск быть отвергнутым и риск взлома в будущих версиях ОС при использовании частных API. Сделайте на свой страх и риск!

Как правило, в большинстве случаев лучшим решением является просмотр модального контроллера.

Смежные вопросы