iOS: отключить авторотация для подвиги
-
28-10-2019 - |
Вопрос
У меня есть вложенная иерархия представления для приложения для iPad, которое поддерживает изменения ориентации. Это выглядит похожим на следующее.
UIViewController
UIView
- UIView
- UIImageView (disable rotation)
- UIImageView
- UIView (disable rotation)
- UIView
- UIView
...
Я хотел бы заблокировать ориентацию для некоторых из моих подзадач, позволяя другим автоматически повышать и изменить размер. Кажется, я не могу понять, как это сделать.
Одним из подходов, похоже, является вращение подписания вручную внутри willAnimateRotationToInterfaceOrientation:
. Анкет Это не особенно привлекательно, учитывая, что SDK выполняет ротацию, которую я бы просто отменил.
Есть ли способ просто отключить изменения ориентации для подзадач или какого -либо другого метода для реструктуризации моей иерархии?
Решение
Авторотация обрабатывается с помощью Uiviewcontroller представления (shouldAutorotateToInterfaceOrientation:
), поэтому один подход заключается в том, чтобы организовать вашу иерархию так, что вращающиеся представления управляются одним контроллером представления, и не отображаемые представления другим контроллером представления. Оба эти представления uiviewcontroller, тогда необходимо добавить в окно/надзор.
Тонкость здесь заключается в том, что если у вас есть два представления контроллера на одном уровне (т.е. добавлено через addSubview:
), только первый контроллер представления (обычно окно rootViewController
) получит shouldAutorotateToInterfaceOrientation:
сообщение.
Я сам использовал этот подход для достижения панели инструментов, которая вращается, а основной вид - нет.
Технические вопросы и ответы Apple QA1688 («Почему мой uiviewcontroller не вращается с устройством?») Немного рассказывает об этой проблеме.
Обновление для iOS 6:
Авторотация теперь использует UIViewController
S. shouldAutorotate
а также supportedInterfaceOrientations
методы shouldAutorotate
возврат YES
по умолчанию, но помните, что контроллер представления, отличный от rootViewController
чей представление является прямым подемой окна, в любом случае не получит обратные вызовы вращения.
Пример кода для iOS 6:
Создайте новый проект, используя шаблон «Приложение для приложения для просмотра» и убедитесь, что проверяется «использование раскадровки». Мы будем использовать предоставленные ViewController
класс как вращающийся контроллер представления (переименовать его, если хотите!), И создайте секунду UIViewController
Подкласс называется NonRotatingViewController
. Анкет Хотя этот контроллер представления никогда даже не получит обратные вызовы вращения, для полноты и ясности добавить следующий код в NonRotatingViewController.m
:
- (BOOL)shouldAutorotate
{
return NO;
}
в MainStoryboard
файл, перетащите новый объект контроллера представления и установите свой класс на NonRotatingViewController
, и установите свой идентификатор раскадровки на «Незащитный VVC». Пока вы там, измените цвет фона вида вращающегося представления, чтобы очистить (не вращающийся вид будет добавлено под этим) и добавьте метку в каждый вид. В AppDelegate.m
, добавить следующий код:
#import "NonRotatingViewController.h"
// ...
// ...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
NonRotatingViewController *nonRotatingVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"NonRotatingVC"];
[self.window addSubview:nonRotatingVC.view];
return YES;
}
Это просто создание контроллера не вращающегося представления и добавление его представления непосредственно в окно (nb на данный момент в окне rootViewController
уже был установлен раскадровкой).
Запустите проект. Поверните устройство и чудеса при виде одной повернутой метки, а другая остается на месте!
Пример кода до iOS 6:
Я сделал это в новом проекте - новое приложение, основанное на просмотре, подойдет просто. Добавьте два новых контроллера представления: RotatingViewController
а также NonRotatingViewController
. Анкет Внутри каждого из их печи я только что добавил этикетку, чтобы описать, должно ли представление вращаться или нет. Добавьте следующий код:
'RotatingViewController.m
'
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
'NonRotatingViewController.m
'
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) { // Or whatever orientation it will be presented in.
return YES;
}
return NO;
}
'AppDelegate.m
'
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RotatingViewController *rotating = [[RotatingViewController alloc] initWithNibName:@"RotatingViewController" bundle:nil];
self.rotatingViewController = rotating;
[rotating release];
NonRotatingViewController *nonRotating = [[NonRotatingViewController alloc] initWithNibName:@"NonRotatingViewController" bundle:nil];
self.nonRotatingViewController = nonRotating;
[nonRotating release];
[self.window addSubview:self.rotatingViewController.view];
[self.window insertSubview:self.nonRotatingViewController.view belowSubview:self.rotatingViewController.view];
[self.window makeKeyAndVisible];
return YES;
}
Надеюсь, это поможет.
Другие советы
Вот другой способ. Просто поместите этот код в свой ViewController ViewDidload:
YourAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
// the view you don't want rotated (there could be a heierarchy of views here):
UIView *nonRotatingView = [[UIView alloc] initWithFrame:CGRectMake(100,0,30,500)];
nonRotatingView.backgroundColor = [UIColor purpleColor];
// make sure self.view and its children are transparent so you can see through to this view that will not be rotated behind self.view.
[delegate.window insertSubview:nonRotatingView belowSubview:self.view];
// you can't put it in the front using:
// [delegate.window insertSubview:nonRotatingView aboveSubview:self.view];
// It will show up the same as before
// you should declare nonRotatingView as a property so you can easily access it for removal, etc.
Мой подход к решению этой проблемы - это противодействие, используя UINotification
Чтобы обнаружить автоматическое вращение и вращение вида наоборот.
Найдите полный код здесь:
https://gist.github.com/ffraenz/5945301
- (void)orientationDidChangeNotificationReceived:(NSNotification *)notification
{
// find out needed compass rotation
// (as a countermeasure to auto rotation)
float rotation = 0.0;
if (self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
rotation = M_PI;
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
rotation = M_PI / 2.0;
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
rotation = M_PI / (- 2.0);
// rotate compass without auto rotation animation
// iOS rotation animation duration is 0.3
// this excludes the compassView from the auto rotation
// (same effect as in the camera app where controls do rotate and camera viewport don't)
[UIView animateWithDuration:0.3 animations:^(void) {
self.compassView.transform = CGAffineTransformMakeRotation(rotation);
}];
}