Как программно установить ориентацию устройства в iOS 7?
Я работаю над приложением для iPad, используя AutoLayout, где, если пользователь включает определенный режим (режим "голова-вверх"), я хочу поддерживать только портретную (или портретную вверх ногами) ориентацию и, более того, если устройство находится в пейзаж, я хотел бы автоматически переключиться в портретный режим.
В контроллере вида сверху у меня есть следующее:
- (NSUInteger) supportedInterfaceOrientations {
if (self.modeHeadsUp) {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
} else {
return UIInterfaceOrientationMaskAll;
}
}
- (BOOL) shouldAutorotate {
return TRUE;
}
Основываясь на ответах, которые я видел в другом месте здесь, кажется, что я должен использовать "application setStatusBarOrientation". Поэтому в методе, в котором пользователь выбрал режим "один на один", я включил:
UIApplication *application = [UIApplication sharedApplication];
[application setStatusBarOrientation:UIInterfaceOrientationPortrait
animated:YES];
Тем не менее, это просто ничего не делает. Хотя я могу физически переместить устройство, чтобы оно повернулось в портретное положение, оно не делает это автоматически.
На самом деле, когда в ландшафтном режиме после запуска вышеуказанного кода попытка программно установить ориентацию, когда я запрашиваю приложение "statusBarOrientation" со следующим кодом, оно остается на "4" для ландшафтного:
UIApplication *application = [UIApplication sharedApplication];
int orientation = [application statusBarOrientation];
self.movesTextView.text = [NSString stringWithFormat:@"ORIENTATION %d", orientation];
Казалось, что, возможно, autolayout не запускается с помощью setStatusBarOrientation, поэтому я попытался добавить этот код после, но безрезультатно:
[super updateViewConstraints];
[self.view updateConstraints];
Я понимаю, что Apple хочет оставить ориентацию устройства в руках пользователя. Тем не менее, я хотел бы иметь возможность поддерживать ландшафтный режим, когда не в режиме "один на один".
Я что-то упускаю, чтобы заставить меня изменить ориентацию?
Ответы
Ответ 1
Для iOS 7 и 8:
Objective-C:
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
Свифт 3+:
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
Я называю это в - viewDidAppear:
Ответ 2
Используйте это. Идеальное решение проблемы ориентации..ios7 и ранее
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:@"orientation"];
Ответ 3
Вам нужно позвонить attemptRotationToDeviceOrientation (UIViewController)
, чтобы система вызвала ваш supportedInterfaceOrientations
, когда условие изменилось.
Ответ 4
Это работает для меня на Xcode
6 и 5.
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait);
}
Ответ 5
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
работает, но вы должны вернуть shouldAutorotate с YES в вашем контроллере просмотра
- (BOOL)shouldAutorotate
{
return self.shouldAutoRotate;
}
Но если вы это сделаете, ваш VC будет авторотировать, если пользователь поворачивает устройство...
поэтому я изменил его на:
@property (nonatomic, assign) BOOL shouldAutoRotate;
- (BOOL)shouldAutorotate
{
return self.shouldAutoRotate;
}
и я вызываю
- (void)swithInterfaceOrientation:(UIInterfaceOrientation)orientation
{
self.rootVC.shouldAutoRotate = YES;
NSNumber *value = [NSNumber numberWithInt: orientation];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
чтобы принудительно установить новую ориентацию нажатием кнопки.
Чтобы отменить shouldAutoRotate на NO, я добавил в свой rootVC
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
self.shouldAutoRotate = NO;
}
PS: Это обходное решение действительно работает и во всех симуляторах.
Ответ 6
Единственный способ, который работал у меня, - создать фиктивный modal view controller.
UIViewController* dummyVC = [[UIViewController alloc] init];
dummyVC.view = [[UIView alloc] init];
[self presentModalViewController:dummyVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
Ваш VC будет запрашивать обновленные ориентации интерфейса, когда диспетчер модального просмотра отклоняется.
Любопытно, что UINavigationController делает именно это при нажатии/выводе дочерних контроллеров представления с различными поддерживаемыми ориентациями интерфейса (проверено на iOS 6.1, 7.0).
Ответ 7
Это решение позволяет принудительно установить определенную ориентацию интерфейса, временно переопределив значение UIDevice.current.orientation
и затем попросив систему повернуть интерфейс в соответствии с вращением устройства:
Важно: это взлом и может перестать работать в любой момент
Добавьте в контроллер корневого приложения приложение:
class RootViewController : UIViewController {
private var _interfaceOrientation: UIInterfaceOrientation = .portrait
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask(from: _interfaceOrientation) }
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return _interfaceOrientation }
override func viewDidLoad() {
super.viewDidLoad()
// Register for notifications
NotificationCenter.default.addObserver(self, selector: #selector(RootViewController.handleInterfaceOrientationChangeRequestedNotification(_:)), name: .interfaceOrientationChangeRequested, object: nil)
}
deinit { NotificationCenter.default.removeObserver(self) }
func handleInterfaceOrientationChangeRequestedNotification(_ notification: Notification) {
guard let interfaceOrientation = notification.object as? UIInterfaceOrientation else { return }
_interfaceOrientation = interfaceOrientation
// Set device orientation
// Important:
// • Passing a UIDeviceOrientation here doesn't work, but passing a UIInterfaceOrientation does
// • This is a hack, and could stop working at any moment
UIDevice.current.setValue(interfaceOrientation.rawValue, forKey: "orientation")
// Rotate the interface to the device orientation we just set
UIViewController.attemptRotationToDeviceOrientation()
}
}
private extension UIInterfaceOrientationMask {
init(from interfaceOrientation: UIInterfaceOrientation) {
switch interfaceOrientation {
case .portrait: self = .portrait
case .landscapeLeft: self = .landscapeLeft
case .landscapeRight: self = .landscapeRight
case .portraitUpsideDown: self = .portraitUpsideDown
case .unknown: self = .portrait
}
}
}
extension Notification.Name {
static let interfaceOrientationChangeRequested = Notification.Name(rawValue: "interfaceOrientationChangeRequested")
}
Убедитесь, что все ориентации интерфейса отмечены в разделе "Информация о развертывании":
![Ориентация интерфейса]()
Запросите изменения ориентации интерфейса там, где они вам нужны:
NotificationCenter.default.post(name: .interfaceOrientationChangeRequested, object: UIInterfaceOrientation.landscapeRight)
Ответ 8
Если вы хотите заблокировать основной вид своего приложения на портрете, но хотите открыть всплывающие окна в альбомной ориентации, а вы используете tabBarController как rootViewController, как и я, вы можете использовать этот код в AppDelegate.
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UITabBarController *tabBarController;
@end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Create a tab bar and set it as root view for the application
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
...
}
- (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController
{
return UIInterfaceOrientationPortrait;
}
Это работает очень хорошо.
В вашем viewController, который вы хотите представить в ландшафте, вы просто используете следующее:
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate {
return YES;
}
Ответ 9
-
Добавьте это утверждение в AppDelegate.h
//whether to allow cross screen marker
@property (nonatomic, assign) allowRotation BOOL;
-
Запишите этот раздел кода в AppDelegate.m
- (UIInterfaceOrientationMask) application: (UIApplication *) supportedInterfaceOrientationsForWindow: application (UIWindow *) window {
If (self.allowRotation) {
UIInterfaceOrientationMaskAll return;
}
UIInterfaceOrientationMaskPortrait return;
}
-
Измените свойство allowRotation
приложения-делегата
Ответ 10
Если у вас есть UIViewController, который должен оставаться в режиме портрета, просто добавьте это переопределение и все будет установлено.
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
Лучшая часть - это анимация, когда это представление отображается, оно уже находится в правильной ориентации.
Ответ 11
Базовый UINavigationController должен иметь следующий обратный вызов, чтобы дочерние элементы могли решить, какую ориентацию они хотят.
-(NSUInteger)supportedInterfaceOrientations {
UIViewController *topVC = self.topViewController;
return topVC.supportedInterfaceOrientations;
}
-(BOOL)shouldAutorotate {
UIViewController *topVC = self.topViewController;
return [topVC shouldAutorotate];
}
Ответ 12
Если вы хотите только портретный режим, в iOS 9 (Xcode 7) вы можете:
- Переход к Info.plist
- Выберите пункт "Поддерживаемые интерфейсные ориентиры"
- Удалить "Пейзаж (левая кнопка дома)" и "Пейзаж (правая кнопка дома)"
![введите описание изображения здесь]()
Ответ 13
У меня была аналогичная проблема, чем у вас. Мне нужно заблокировать ориентацию устройства для некоторых экранов (например, Login) и разрешить вращение в других.
После нескольких изменений и последующих ответов ниже я сделал это:
- Включение всех ориентаций в Project Info.plist.
![введите описание изображения здесь]()
- Отключение ориентации в тех ViewControllers, где мне нужно, чтобы устройство не вращалось, например, на экране "Вход" в моем случае. Мне нужно было переопределить метод
shouldAutorotate
в этом VC:
-(BOOL)shouldAutorotate{
return NO;
}
Надеюсь, это сработает для вас.
Ответ 14
здесь приведен пример FULL WORKING для iOS 7, 8, 9, 10, как изменить ориентацию приложения на его текущую противоположность.
Objective-C
- (void)flipOrientation
{
NSNumber *value;
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if(UIInterfaceOrientationIsPortrait(currentOrientation))
{
if(currentOrientation == UIInterfaceOrientationPortrait)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown];
}
else //if(currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
}
}
else
{
if(currentOrientation == UIInterfaceOrientationLandscapeRight)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
}
else //if(currentOrientation == UIInterfaceOrientationLandscapeLeft)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
}
}
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
}
Swift 3
func flipOrientation() -> Void
{
let currentOrientation : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
var value : Int = 0;
if(UIInterfaceOrientationIsPortrait(currentOrientation))
{
if(currentOrientation == UIInterfaceOrientation.portrait)
{
value = UIInterfaceOrientation.portraitUpsideDown.rawValue
}
else //if(currentOrientation == UIInterfaceOrientation.portraitUpsideDown)
{
value = UIInterfaceOrientation.portrait.rawValue
}
}
else
{
if(currentOrientation == UIInterfaceOrientation.landscapeRight)
{
value = UIInterfaceOrientation.landscapeLeft.rawValue
}
else //if(currentOrientation == UIInterfaceOrientation.landscapeLeft)
{
value = UIInterfaceOrientation.landscapeRight.rawValue
}
}
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
Ответ 15
Попробуйте это вместе с вашим кодом.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
после того, как пользователь выберет любую опцию, затем вызовите этот метод, потому что пользователь может находиться в ландшафтном режиме, а затем он может установить только портретный режим в одном и том же контроллере просмотра, поэтому автоматически просмотр должен быть перемещен в портретный режим, поэтому в этой кнопке acton вызовите это
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
Ответ 16
Это сработало у меня отлично....
NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
Ответ 17
https://www.youtube.com/watch?v=d7QFtyow7TU Это видео поможет вам установить ориентацию экрана в xcode
Ответ 18
Для таких, как я, которые боролись за то, чтобы @Sunny Shah принял ответ на работу на iPad. Вам необходимо установить флажок "Требуется полный экран" в настройках проекта. Обратите внимание, что это помешает вашему приложению работать в многозадачном режиме, который может быть или не быть приемлемым.
![enter image description here]()