Як примусити UIViewController до книжкової орієнтації в iOS 6


85

Оскільки ShouldAutorotateToInterfaceOrientationв iOS 6 застаріло, і я використовував це, щоб змусити певний вигляд лише портретизувати , який правильний спосіб це зробити в iOS 6? Це лише для однієї області мого додатка, всі інші види можуть обертатися.

Відповіді:


117

Якщо ви хочете, щоб усі наші контролери навігації поважали контролер вигляду зверху, ви можете використовувати категорію, щоб вам не довелося проходити і змінювати купу назв класів.

@implementation UINavigationController (Rotation_IOS6)

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

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end

Як зазначають деякі коментарі, це швидке вирішення проблеми. Кращим рішенням є підклас UINavigationController і розміщення цих методів там. Підклас також допомагає підтримувати 6 і 7.


3
Я можу підтвердити, що це працює. Ви також можете замінити "[self.viewControllers lastObject]" на "self.topViewController", якщо хочете.
Wayne Liu

3
Якщо ви використовуєте UITabBarController, ніж ця категорія UINavigationController не допоможе. Натомість вам слід зробити категорію на UITabBarController ...
Борут Томазін

46
Проблема з цим рішенням полягає в тому, що він не працює, коли ви висуваєте контролер, який знаходився в альбомному режимі, а ваш новий верхній контролер підтримує лише портрет (або навпаки), ці зворотні виклики в цьому випадку не викликаються, і я ще не знайшов способу, як змусити новий верхній контролер у правильну орієнтацію. Будь-які ідеї?
Лопе

4
Я підкласифікував UINavigationController і встановив його як window.rootController. Я реалізував усі 3 методи, це чудово працює, коли ви змінюєте обертання пристрою, проблема в тому, що ці методи (і нічого, що стосується обертання) викликаються, коли ви вискакуєте контролер подання
Lope

4
Якщо я роблю натискання або виштовхування з контролера перегляду пейзажів, тоді ця сила UIViewController змінюється на альбомну. Однак якщо я повернуся в книжковий режим, це справно працює, і ніколи не зміниться на альбомний. Єдина проблема під час натискання або вискакування з альбомної орієнтації. Будь ласка, допоможіть
Тарік

63

Найкращий спосіб для iOS6, зокрема, зазначений у "iOS6 By Tutorials" командою Ray Wenderlich - http://www.raywenderlich.com/, і UINavigationControllerдля більшості випадків це краще, ніж підкласифікація .

Я використовую iOS6 з розкадровкою, яка включає UINavigationControllerнабір як початковий контролер перегляду.

//AppDelegate.m - цей спосіб, на жаль, недоступний до iOS6

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;

if(self.window.rootViewController){
    UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
    orientations = [presentedViewController supportedInterfaceOrientations];
}

return orientations;
}

//MyViewController.m - повертає будь-які орієнтації, які ви хочете підтримувати для кожного UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

1
Це найкраще рішення для iOS 6
Homam

2
@Phil, це чудово працює для iOS 6. Але в деяких випадках, наприклад, якщо ви переходите від альбомної до книжкової, це не працює. Будь-яка ідея, чому це відбувається?
Kirti Nikam

1
Дуже корисне рішення. Для мене найкраще.
Оскар Кастельон

1
Робота з iOS 7 beta 6. У моєму випадку працює при переході від альбомного до портретного.
Мартін Бергер

Я працюю в iOS 6, але це не працює. Він порушується в рядку "UIViewController * predstavljenViewController".
Марсель Маріно

39

Ця відповідь стосується питань, заданих у коментарях до допису ОП:

Щоб змусити подання виглядати в заданому напрямку, поставте наступне в viewWillAppear:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
    UIViewController *c = [[UIViewController alloc]init];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}

Це трохи зламано, але це змушує UIViewControllerбути представленим у портретному режимі, навіть якщо попередній контролер був альбомним

ОНОВЛЕННЯ для iOS7

Наведені вище методи тепер застаріли, тому для iOS 7 використовуйте наступне:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
     UIViewController *c = [[UIViewController alloc]init];
     [c.view setBackgroundColor:[UIColor redColor]];
     [self.navigationController presentViewController:c animated:NO completion:^{
            [self.navigationController dismissViewControllerAnimated:YES completion:^{
            }];
     }];
}

Цікаво, що на момент написання статті або подарунок, або звільнення повинні бути анімовані. Якщо ні те, ні інше, ви отримаєте білий екран. Не знаю, чому це змушує це працювати, але це робить! Візуальний ефект різниться залежно від того, який анімований.


Дякую, я спробую, коли знайду кілька хвилин вільного часу
Лопе

@RohanAgarwal він працює, як рекламується, я використовую його тут. Але потрібно також запровадити код прийнятої відповіді, інакше він не спрацює.
Денніс Мансі,

2
Хтось придумував, як зробити цю роботу одночасно з правильною анімацією обертання? Трохи посміхається бачити, як він перемикається з портретного на пейзажний без анімації. Це працює, сподіваючись зробити це трохи кращим.
Денніс Мунсі,

@Craig Watkinson Це не працює в раскадровці. і presentModalViewController і dismissModalViewControllerAnimated засуджується , якщо IAM з допомогою presentVirecontroller то це звичай працювати .Please допомогу мені
Kalpesh

1
Для ios8 dismissViewControllerAnimated просто аварійно завершує роботу. Я виявив, що виклик [NWSAppDelegate sharedInstance] .window.rootViewController = nil; [NWSAppDelegate sharedInstance] .window.rootViewController = previousRootController добре працює.
Олексій

36

Тож я зіткнувся з тією ж проблемою при відображенні портретних лише модальних видів. Зазвичай я створюю a UINavigationController, встановлюю viewControllerяк rootViewController, а потім відображаю UINavigationControllerяк модальний вигляд. Але з iOS 6 viewControllerтепер система запитає у NavigController про підтримувані орієнтації інтерфейсу (який за замовчуванням зараз для iPad і все, крім перевернутого для iPhone).

Рішення : Мені довелося класифікувати UINavigationControllerта замінити методи авторотації. Вид кульгавий.

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}

1
не працює на моєму. У мене був цей код із глобальним налаштуванням для всіх орієнтацій
phil88530

2
supportedInterfaceOrientations повинен повертати NSUInteger, а не BOOL. Див. Developer.apple.com/library/ios/#featuredarticles/…
tomwhipple

це спрацювало, для мене його контролер вкладки, ще раз дякую за відповідь
otakuProgrammer

FWIW, мені довелося пройти і цей шлях ... Більше нічого не вийшло. Дякую.
Steve N

15

IOS 5

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

IOS 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{

    //    UIInterfaceOrientationMaskLandscape;
    //    24
    //
    //    UIInterfaceOrientationMaskLandscapeLeft;
    //    16
    //
    //    UIInterfaceOrientationMaskLandscapeRight;
    //    8
    //
    //    UIInterfaceOrientationMaskPortrait;
    //    2

    //    return UIInterfaceOrientationMaskPortrait; 
    //    or
          return 2;
}

Відмінно! Потрібно бути максимально вгорі цієї теми. Тому що це найпростіший спосіб вирішити проблему
Алекс

@Roshan Jalgaonkar У iOS 6 Це не працює для мене, мені потрібен лише портрет з кнопкою вниз додому, як я можу встановити цю UIO-орієнтацію ....
Картік,

@Karthik, ви повинні ввімкнути підтримувані обертання в цілі вашого додатка, щоб це працювало.
Alejandro Iván

@ AlejandroIván k thnx
Картік

10

Я не погоджуюсь з відповіддю @aprato, оскільки методи обертання UIViewController оголошені в самих категоріях, що призводить до невизначеної поведінки, якщо ви перевизначите, то в іншій категорії. Безпечніше замінити їх у підкласі UINavigationController (або UITabBarController)

Крім того, це не охоплює сценарій, коли ви натискаєте / презентуєте / вискакуєте з альбомного перегляду в портретний ВК або навпаки. Щоб вирішити цю складну проблему (яку Apple ніколи не вирішувала), вам слід:

У iOS <= 4 та iOS> = 6:

UIViewController *vc = [[UIViewController alloc]init];
[self presentModalViewController:vc animated:NO];
[self dismissModalViewControllerAnimated:NO];
[vc release];

У iOS 5:

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];

Вони ДІЙСНО змусять UIKit переоцінити всі ваші функції автоавтоповороту, підтримувані орієнтації інтерфейсу тощо.


2
Перший з цих збоїв для мене незалежно від версії iOS. Каже, звільнення не повинно відбуватися до закінчення присутності.
Арсеній

@arsenius Чи можете ви опублікувати фрагмент того, як ви ним користуєтесь? Поки він не анімований, він не повинен мати проблеми, про яку ви згадали
Рафаель Нобре

Я також розмістив другий фрагмент у viewDidAppear, і він нічим не допомагає моїй ситуації на iOS 6. Питання тут: stackoverflow.com/questions/15654339/…
arsenius

Вибачте, останній коментар тут. Переміщення коду iOS 5 до viewDidAppear створює якийсь нескінченний цикл із цим висновком: - [UIApplication beginIgnoringInteractionEvents] переповнення. Ігнорування.
arsenius

3

У мене дуже хороший підхід до змішування https://stackoverflow.com/a/13982508/2516436 та https://stackoverflow.com/a/17578272/2516436

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;


    if(self.window.rootViewController){
        UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController];
        orientations = [presentedViewController supportedInterfaceOrientations];
    }

    return orientations;
}

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}

і поверніть будь-які орієнтації, які ви хочете підтримувати для кожного UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

1

У мене є відносно складний універсальний додаток, що використовує UISplitViewController та UISegmentedController, і маю кілька поглядів, які повинні бути представлені в альбомній орієнтації presentViewController . Використовуючи запропоновані вище методи, я зміг змусити iPhone ios 5 і 6 працювати прийнятно, але з якихось причин iPad просто відмовився представити як Пейзаж. Нарешті, я знайшов просте рішення (реалізоване після годин читання та спроб і помилок), яке працює як для пристроїв, так і для iOS 5 та 6.

Крок 1) На контролері вкажіть необхідну орієнтацію (більш-менш, як зазначено вище)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    NSInteger mask = UIInterfaceOrientationMaskLandscape;
    return mask;

}

Крок 2) Створіть простий підклас UINavigationController та застосуйте наступні методи

-(BOOL)shouldAutorotate {
        return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskLandscape;
}

Крок 3) Представте свій viewController

vc = [[MyViewController alloc]init];
MyLandscapeNavigationController *myNavigationController = [[MyLandscapeNavigationController alloc] initWithRootViewController:vc];
[self myNavigationController animated:YES completion:nil];

Сподіваюся, це комусь корисно.


1

Щоб не бути нудним тут, але чи могли б ви так люб’язно поділитися своїм підкласом? Дякую.

edit: ну, нарешті я це зробив, підклас було просто зробити просто. Мені просто потрібно було оголосити navigationControllerin AppDelegateяк UINavigationControllerSubclassзамість типового UINavigationController, а потім змінити ваш підклас за допомогою:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

так що я можу встановити будь-який вигляд, який я хочу повернути чи ні, зателефонувавши за номером viewDidLoad

_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]

Сподіваємось, цей твік допоможе і іншим, дякую за підказку!

Порада. Використовуйте

- (NSUInteger)supportedInterfaceOrientations

у ваших контролерах перегляду, так що в кінцевому підсумку ви не отримаєте портретний бажаний вигляд в альбомному або навпаки.


0

Я не тестував його сам, але в документації зазначено, що тепер ви можете замінити ці методи: supportedInterfaceOrientationsіpreferredInterfaceOrientationForPresentation .

Ви, мабуть, можете досягти бажаного, встановивши лише орієнтацію, яку хочете в цих методах.


0

Відповіді з використанням підкласів або категорій, щоб дозволити VC у класах UINavigationController та UITabBarController, працюють добре. Не вдалося запустити портретний модаль із контролера горизонтальної панелі вкладок. Якщо вам потрібно це зробити, скористайтесь фокусом відображення та приховування неінімованого модального подання, але зробіть це за допомогою методу viewDidAppear . Мені це не вдалося у viewDidLoad або viewWillAppear.

Окрім цього, наведені вище рішення працюють чудово.


0

Для Monotouch ви можете зробити це таким чином:

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
    {
    return UIInterfaceOrientationMask.LandscapeRight;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation()
    {
    return UIInterfaceOrientation.LandscapeRight;
}


-1

Просто перейдіть до project.plist, потім додайте Підтримувана орієнтація інтерфейсу, а потім додайте лише Портрет (нижня кнопка додому) та Портрет (кнопка додому вгорі).

Ви можете додати або видалити там орієнтацію відповідно до вимог вашого проекту.

Дякую


1
мова йде про конкретний контролер перегляду не для цілого додатка.
Мухаммед Різван

-2

1) Перевірте налаштування проекту та info.plist та переконайтеся, що вибрані лише ті орієнтації, які ви хочете

2) додайте наступні методи до свого верхнього контролера перегляду (контролер навігації / контролер панелі вкладок)

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

3) додайте такі способи до делегата програми

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskPortrait;

}

-3

Помістіть це у файл .m кожного, який ViewControllerви не хочете обертати:

- (NSUInteger)supportedInterfaceOrientations
{
    //return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
    return UIInterfaceOrientationMaskPortrait;
}

Дивіться тут для отримання додаткової інформації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.