Поддержка ландшафта только для одного представления в UINavigationController - PullRequest
13 голосов
/ 17 февраля 2011

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

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

Как повернуть экран в альбомную ориентацию?

КакАвтоповорот из портретного в ландшафтный режим? iPhone - разрешить альбомную ориентацию только на одном контроллере вида http://goodliffe.blogspot.com/2009/12/iphone-forcing-uiview-to-reorientate.html

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

Если у кого-то есть идея получше, пожалуйста, дайте мне знать.Очень признателен!

ОБНОВЛЕНИЕ: Я успешно использую метод, описанный выше: замените pushViewController на presentModalViewController и создайте новый контроллер навигации.

Ответы [ 5 ]

9 голосов
/ 09 июня 2012

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

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

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

  1. Создайте «поддельный» контроллер представления, который будет корневым в дополнительном навигационном контроллере.Этот контроллер представления должен поддерживать ландшафт.
  2. Создать новый экземпляр UINavigationController, добавить экземпляр «поддельного» контроллера представления в качестве пользователя root и экземпляр вашего контроллера ландшафта в качестве второго контроллера представления
  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 голос
/ 10 декабря 2012

Существует частный API для принудительного изменения ориентации. Поместите в ваш контроллер Push View -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. Делай на свой страх и риск!

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

0 голосов
/ 15 апреля 2011

Вы можете попробовать этот код в 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 голосов
/ 23 сентября 2011

Вы можете совершать действия: Измените Ваш код в соответствии с предложением Schellsan, далее - Попробуйте добавить currentViewController (который будет перемещен в навигационный viewController) как свойство appDelegate Когда вы пытаетесь выдвинуть контроллер представления, установите его на текущий контроллер представления перед этим. Далее - сделать подкласс rootViewController в контроллере навигации. В этом подклассе метод рабочей нагрузки

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

Должно работать, если вы не используете навигационную панель и толкает новый контроллер после установки старого

0 голосов
/ 17 февраля 2011

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

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

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

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

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

[[self topViewController] shouldAutorotateToInterfaceOrientation:interfaceOrientation];
...