13

Mam kontroler nawigacyjny, który ma kilka kontrolerów widoku. Potrzebuję obsługi wszystkich orientacji dla wszystkich kontrolerów widoku z wyjątkiem jednego specjalnego kontrolera widoku, który obsługuje tylko krajobraz. Ten specjalny kontroler widoku pojawia się na środku stosu nawigacji. Zrobiłem sporo badań, ale nie mogłem znaleźć dobrego rozwiązania. Oto linki, które przeczytałem i wypróbowałem.Wsparcie dla tylko jednego widoku w 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

Następny mam zamiar spróbować zastąpić kontroler nawigacyjny z presentModalViewController w celu wyświetlenia specjalnego kontrolera widoku. Następnie utworzę nowy kontroler widoku nawigacyjnego wewnątrz specjalnego kontrolera widoku, aby wypchnąć kolejne kontrolery widoku.

Jeśli ktoś ma lepszy pomysł, proszę dać mi znać. Naprawdę doceniony!

UPDATE: ja z powodzeniem zastosować metodę opisałem powyżej: wymienić pushViewController z presentModalViewController i utworzyć nowy kontroler nawigacyjny.

+0

Czy możesz udostępnić przykładowy kod? –

Odpowiedz

8

każdy widok popychane na nawigacji kontrolery stosu muszą obsługiwać te same kierunki. Oznacza to, że nie jest możliwe posiadanie niektórych kontrolerów widoku obsługujących tylko portret i innych tylko wspierających krajobraz.Innymi słowy wszystkie kontrolery widok na tym samym stosie kontroler nawigacji powinien wrócić w to samo delegata:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

Ale istnieje proste rozwiązanie tego! Oto przykład przejścia z portretu na krajobraz. Oto kroki, aby to zrobić, a poniżej znajduje się kod do jego obsługi.

  1. Utwórz "fałszywy" kontroler widoku, który będzie rootem w podrzędnym kontrolerze nawigacyjnym. Ten kontroler widoku powinien wspierać krajobraz.
  2. Utwórz nową instancję UINavigationController, dodać instancję „fałszywego” widoku kontrolera jako root i instancję kontrolera widoku krajobrazu jako drugi widok kontrolera
  3. przedstawić instancji UINavigationController jako modalnego z kontrolera widoku rodzica

Najpierw utwórz nowy kontroler widoku (FakeRootViewController) z tym kodem:

@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)); 
} 

Oto kod do zaprezentowania kontroler widoku, który chcesz pokazać w Tryb krajobrazu:

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]; 

Pamiętaj, że landscapeViewController powinna także mieć tę realizacji:

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

+50 amazeballs. – Adam

+0

Wreszcie prosta odpowiedź. – Jeef

0

To powinno być tak proste, jak wdrożenie

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

w każdym UIViewController wepchnięta do swojej UINavigationController. W przypadku, gdy jeden widok UIViewController nie powinien się obracać, return NO dla tej określonej orientacji w tym konkretnym UIViewController. Nie ma haczyka tutaj chociaż, jeśli UINavigationController realizuje

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

będzie blokować jego viewControllers od otrzymania tej metody. W takim przypadku należy przesłać wiadomość do topViewController użyciu

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

Chciałbym, żeby to było takie proste. Czy próbowałeś tego? Jest z tym kilka problemów. 1. W przypadku renderowania specjalnego widoku poziomego, gdy telefon jest portretem, po ustawieniu telefonu w pozycji poziomej widok zostanie obrócony, aby niespodziewanie uzyskać portret. 2. Po pierwszym wyrenderowaniu specjalnego widoku krajobrazu, a następnie obróceniu telefonu do portretu, a następnie wyjściu z widoku specjalnego i ponownym otwarciu widok zostanie nieoczekiwanie obrócony. Wygląda to na problem z kontrolerem nawigacyjnym i naprawdę chcę, żeby Apple działało zgodnie z opisem. –

+0

Próbowałem. Myślę, że problemy, które napotykasz, mogą być specyficzne dla Twojej aplikacji. Spróbuj rozpocząć nowy projekt, aby wyizolować problem rotacji UINavigationController, a następnie przeprowadź eksperymenty. – schellsan

0

Można wypróbować ten kod w swoim UINavigationController zadzwonić obecny widoczny widok na shouldAutorotateToInterfaceOrientation. W moim przypadku mam UINavigationController w UITabBarController, ale prawdopodobnie możesz dostosować go do innych przypadków.

- (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

Można dokonać czynności: zmiany kodu z zgodnie z schellsan sugestią, obok - Spróbuj dodać currentViewController (która będzie pchać do nawigacji viewController) jako własność do appDelegate. Podczas próby naciśnięcia kontrolera widoku ustaw go na bieżący kontroler widoku. Następnie - wykonaj podklasę rootViewController w kontrolerze nawigacyjnym. W podklasie tej metody owerload

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

Powinna ona działa, jeśli nie używasz paska nawigacyjnego i popycha nowy kontroler po popping stary kontroler

+3

Jak osiągnąć to samo z wersją iOS 6. – Krishnan

1

Jest prywatny API, aby wymusić zmianę orientacji. Umieścić w pchnął widok kontrolera -viewWillAppear::

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

Aby stłumić ostrzeżenia kompilatora, dodać to do pliku .m swojego kontrolera widoku:

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

Jak zawsze istnieje ryzyko odrzucenia i ryzyko złamania w przyszłych wersjach systemu operacyjnego podczas korzystania z prywatnych interfejsów API. Rób na własne ryzyko!

Ogólnie rzecz biorąc, przedstawienie modalnego kontrolera widoku jest lepszym rozwiązaniem w większości przypadków.

Powiązane problemy