IOS 6 принудительная ориентация устройства на ландшафт
Я дал приложение с скажем 10 контроллеров вида. Я использую навигационный контроллер для загрузки / выгрузки их.
все, кроме одного, находятся в портретном режиме. Предположим, что 7-й VC находится в ландшафте. Мне нужно, чтобы он был представлен в ландшафте, когда он загружается.
пожалуйста, предложите способ заставить ориентацию перейти от портретной к альбомной в IOS 6 (и это будет хорошо работать в iOS 5, а).
вот как я это делаю до IOS 6:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIViewController *c = [[[UIViewController alloc]init] autorelease];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
представление и отклонение модального VC заставляло приложение пересматривать свою ориентацию, поэтому shouldAutorotateToInterfaceOrientation
был вызван.
что я пробовал в IOS 6:
- (BOOL)shouldAutorotate{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationLandscapeLeft;
}
на нагрузке, регулятор держит остаться в портрете. После поворота устройства ориентация меняется просто нормально. Но мне нужно, чтобы контроллер автоматически вращался для ландшафта при загрузке, поэтому пользователю придется повернуть устройство, чтобы увидеть данные правильно.
еще одна проблема: после поворота устройства обратно в портрет, ориентация переходит в портрет, хотя я указал в supportedInterfaceOrientations
только UIInterfaceOrientationMaskLandscape
. Почему это происходит?
и нет из выше 3 методов вызываются.
некоторые (полезные) данные:
- в моем файле plist я указал 3 ориентации - все, кроме вверх ногами.
- проект был запущен в Xcode 4.3 IOS 5. Все классы, включая xibs, были созданы до Xcode 4.5 IOS 6, теперь я использую последнюю версию.
- в файле plist строка состояния имеет значение видимый.
- в файле xib (тот, который я хочу быть в альбомной ориентации) строка состояния "нет", ориентация установлена в альбомной ориентации.
любая помощь приветствуется. Спасибо.
13 ответов:
хорошо, ребята, я опубликую свое решение.
что у меня есть:
- приложение на основе представления, с несколькими контроллерами представления. (Это была навигация на основе, но я должен был сделать его вид на основе, из-за проблем ориентации).
- все контроллеры вида являются портретными, за исключением одного-landscapeLeft.
задачи:
- один из моих контроллеров вида должен автоматически поворачиваться в альбомную ориентацию, независимо от того, как пользователь держит устройство. Все остальные контроллеры должны быть портретными, и после выхода из ландшафтного контроллера приложение должно принудительно поворачиваться к портрету, независимо от того, как пользователь держит устройство.
- это должно работать как на IOS 6.x как на IOS 5.x
вперед!
(обновление удалены макросы, предложенные @Ivan Vučica)
во всех ваших контроллерах портретного вида переопределяются методы авторотации, такие как это:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ return (toInterfaceOrientation == UIInterfaceOrientationPortrait); } -(BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; }
вы можете увидеть 2 подхода: один для IOS 5 и другой для IOS 6.
то же самое для вашего контроллера ландшафтного вида, с некоторыми дополнениями и изменениями:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ [image_signature setImage:[self resizeImage:image_signature.image]]; return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft); } -(BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { [image_signature setImage:[self resizeImage:image_signature.image]]; return UIInterfaceOrientationMaskLandscapeLeft; }
внимание: для принудительной авторотации в IOS 5 вы должны добавить это:
- (void)viewDidLoad{ [super viewDidLoad]; if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0) [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO]; }
аналогично, после того, как вы покинете ландшафтный контроллер, какой бы контроллер вы ни загрузили, вы должны снова заставить авторотация для IOS 5, но теперь вы будете использовать
UIDeviceOrientationPortrait
, как вы идете к портретному контроллеру:- (void)viewDidLoad{ [super viewDidLoad]; if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0) [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO]; }
теперь последнее (и это немного странно) - вы должны изменить способ переключения с одного контроллера на другой, в зависимости от IOS:
создайте класс NSObject "Schalter" ("переключатель" с немецкого языка).
В Coupe ' Спортивный.ч. сказала:
#import <Foundation/Foundation.h> @interface Schalter : NSObject + (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease; @end
В Coupe ' Спортивный.м говорю:
#import "Schalter.h" #import "AppDelegate.h" @implementation Schalter + (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{ //adjust the frame of the new controller CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame]; CGRect windowFrame = [[UIScreen mainScreen] bounds]; CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height); VControllerToLoad.view.frame = firstViewFrame; //check version and go if (IOS_OLDER_THAN_6) [((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view]; else [((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad]; //kill the previous view controller [VControllerToRelease.view removeFromSuperview]; } @end
теперь, это, как вы используйте Schalter (предположим, вы переходите от контроллера склада к контроллеру продуктов):
#import "Warehouse.h" #import "Products.h" @implementation Warehouse Products *instance_to_products; - (void)goToProducts{ instance_to_products = [[Products alloc] init]; [Schalter loadController:instance_to_products andRelease:self]; } bla-bla-bla your methods @end
конечно, вы должны освободить
Это должно работать, это похоже на версию до iOS 6, но с
UINavigationController
:UIViewController *portraitViewController = [[UIViewController alloc] init]; UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController]; [self.navigationController presentModalViewController:nc animated:NO]; [self.navigationController dismissModalViewControllerAnimated:NO];
я называю это, прежде чем я нажимаю на следующий
UIViewController
. Это заставит следующий толкнулUIViewController
для отображения в портретном режиме, даже если токUIViewController
находится в ландшафте (должен работать для портрета в ландшафт тоже). Работает на iOS 4+5+6 для меня.
Я думаю, что лучшее решение-придерживаться официальной документации apple. Поэтому в соответствии с этим я использую следующие методы, и все работает очень хорошо на iOS 5 и 6. В моем VC я переопределяю следующие методы:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return UIInterfaceOrientationIsPortrait(interfaceOrientation); }
методы для iOS 6, Первый метод возвращает поддерживаемую маску ориентации (как указано в их названии)
-(NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskPortrait; }
второй, который говорит ваш VC, который является предпочтительной ориентацией интерфейса, когда VC будет отображаться.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; }
просто измените портрет для ориентации, которую вы хотите ;) Это решение работает гладко, мне не нравится идея создания макросов и других вещей, которые идут вокруг этого простого решения. Надеюсь, это поможет...
у меня была та же проблема, 27 просмотров в моем приложении, из которых 26 в портрете и только один во всех ориентациях ( просмотрщик изображений :) ). Добавление макроса на каждый класс и замена навигации не было решением, с которым мне было комфортно...
Итак, я хотел сохранить механику UINavigationController в своем приложении и не заменять ее другим кодом.
Что делать:
@1 в делегате приложения в методе didFinishLaunchingWithOptions
if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0) { // how the view was configured before IOS6 [self.window addSubview: navigationController.view]; [self.window makeKeyAndVisible]; } else { // this is the code that will start the interface to rotate once again [self.window setRootViewController: self.navigationController]; }
@2 Поскольку navigationController просто ответит Да для авторотации нам нужно добавить некоторые ограничения: Расширьте UINavicationController - > YourNavigationController и свяжите его в Построителе интерфейса.
@3 переопределить "anoying новые методы" от навигационного контроллера.
Так как этот класс специально только для этого приложения, он может взять на себя ответственность ибо это контроллеры и отвечают в своих место.
-(BOOL)shouldAutorotate { if ([self.viewControllers firstObject] == YourObject) { return YES; } return NO; } - (NSUInteger)supportedInterfaceOrientations { if ([self.viewControllers firstObject] == YourObject) { return UIINterfaceOrientationMaskLandscape; } return UIInterfaceOrientationMaskPortrait; }
Я надеюсь, что это поможет вам,
Теперь контейнеры iOS (такие как UINavigationController) не консультируются со своими детьми, чтобы определить, следует ли им авторотировать.
ваша
rootViewController
передатьshouldAutoRotate
сообщение отViewController
иерархия для вашего ВК?
я использовал тот же метод, что и OP pre-ios6 (представить и отклонить модальный VC), чтобы показать один контроллер вида в ландшафтном режиме (все остальные в портретном). Он сломался в ios6 с пейзажем VC, показанным в портрете.
чтобы исправить это, я просто добавил метод preferredInterfaceOrientationForpresentation в ландшафтном VC. Кажется, теперь отлично работает для os 5 и os 6.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft); } - (BOOL)shouldAutorotate { return NO; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationLandscapeLeft; }
Эй, ребята после tryng много различных возможных решений без успеха я вышел со следующим решением надеюсь, что это поможет!.
Я приготовил рецепт :).
: вам нужно изменить ориентацию viewcontrollers с помощью navigationcontroller в ios 6.
устранение:
Шаг 1. один начальный UIviewcontroler для запуска модальных сегментов в ландшафт и портрет UInavigationControllers как показано на рисунке....
более глубоко в UIViewController1 нам нужно 2 сегментирует действия в соответствии с глобальной переменной в Appdelegate....
-(void)viewDidAppear:(BOOL)animated{ if([globalDelegate changeOrientation]==0){ [self performSegueWithIdentifier:@"p" sender:self]; } else{ [self performSegueWithIdentifier:@"l" sender:self]; } }
также нам нужно вернуться к портрету и / пейзажу....
- (IBAction)dimis:(id)sender { [globalDelegate setChangeOrientation:0]; [self dismissViewControllerAnimated:NO completion:nil]; }
Шаг 2. первый нажал UiViewControllers на каждом NavigationController идет с...
-(NSUInteger)supportedInterfaceOrientations{ return [self.navigationController supportedInterfaceOrientations]; } -(BOOL)shouldAutorotate{ return YES; }
Шаг 3. мы перезаписываем метод supportedInterfaceOrientations на подкласс UInavigationController....
в вашем customNavigationController у нас есть .....
-(NSUInteger)supportedInterfaceOrientations{ if([self.visibleViewController isKindOfClass:[ViewController2 class]]){ return UIInterfaceOrientationMaskPortrait; } else{ return UIInterfaceOrientationMaskLandscape; } }
Шаг 4. в раскадровке или по коду установите флаг wantsFullScreenLayout в yes, как для портретных, так и для ландшафтных uinavigationcontrollers.
попробуйте segueing к
UINavigationController
который использует категорию или подкласс, чтобы указать желаемую ориентацию, а затем перейти к желаемому VC. Читать дальше здесь.
в качестве альтернативы вы можете сделать то же самое используя блоки:
UIViewController *viewController = [[UIViewController alloc] init]; viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; [self presentViewController:viewController animated:NO completion:^{ [self dismissViewControllerAnimated:NO completion:nil]; }];
кроме того, вызовите его перед нажатием нового представления.
У меня была та же проблема. Если вы хотите, чтобы определенный контроллер вида отображался в альбомной ориентации, сделайте это прямо перед тем, как поместить его в стек навигации.
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if (currentOrientation == UIInterfaceOrientationPortrait || currentOrientation == UIInterfaceOrientationPortraitUpsideDown) [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft]; UIViewController *vc = [[UIViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; [vc release];
Я решил это путем подкласса UINavigationController и переопределения supportedInterfaceOrientations навигационного контроллера следующим образом:
- (NSUInteger)supportedInterfaceOrientations { return [[self topViewController] supportedInterfaceOrientations]; }
все контроллеры реализовали supportedInterfaceOrientations с их желаемыми ориентациями.
я использовал следующее решение. В одном контроллере вида, который имеет другую ориентацию, чем все остальные, я добавил проверку ориентации в prepareForSegue метод. Если контроллеру вида назначения требуется ориентация интерфейса, отличная от текущей, то отправляется сообщение, которое заставляет интерфейс вращаться во время seque.
#import <objc/message.h>
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)) { UIInterfaceOrientation destinationOrientation; if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]]) { UINavigationController *navController = (UINavigationController *)[segue destinationViewController]; destinationOrientation = [navController.topViewController preferredInterfaceOrientationForPresentation]; } else { destinationOrientation = [[segue destinationViewController] preferredInterfaceOrientationForPresentation]; } if ( destinationOrientation == UIInterfaceOrientationPortrait ) { if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait ); } } } }