如何在iOS 7中以编程方式设置设备方向?
我正在使用AutoLayout开发一个iPad应用程序,如果用户启用某个模式(“抬头”模式),我只想支持纵向(或纵向倒置)方向,而且,如果设备处于横向,我想自动切换到纵向模式 在俯视图控制器中,我有以下内容:如何在iOS 7中以编程方式设置设备方向?,ios,xcode,ios7,autolayout,autorotate,Ios,Xcode,Ios7,Autolayout,Autorotate,我正在使用AutoLayout开发一个iPad应用程序,如果用户启用某个模式(“抬头”模式),我只想支持纵向(或纵向倒置)方向,而且,如果设备处于横向,我想自动切换到纵向模式 在俯视图控制器中,我有以下内容: - (NSUInteger) supportedInterfaceOrientations { if (self.modeHeadsUp) { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrient
- (NSUInteger) supportedInterfaceOrientations {
if (self.modeHeadsUp) {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
} else {
return UIInterfaceOrientationMaskAll;
}
}
- (BOOL) shouldAutorotate {
return TRUE;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate {
return YES;
}
根据我在其他地方看到的答案,答案似乎是我应该使用“应用程序setStatusBaroOrientation”。因此,在用户选择“抬头”模式的方法中,我包括:
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];
似乎SetStatusBaroOrientation没有触发autolayout,所以我尝试在之后添加此代码,但没有任何效果:
[super updateViewConstraints];
[self.view updateConstraints];
我意识到苹果想把设备定位权交给用户。但是,我希望在不处于“平视”模式时能够支持横向模式
我是否错过了强制改变方向的功能?对于iOS 7和8:
目标C:
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
Swift 3+:
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
我在
-viewdide中调用它:
请将此与您的代码一起尝试。-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
一旦用户选择任何选项,然后调用此方法,因为用户可以处于横向模式,然后他可以在同一视图控制器中仅设置纵向模式,所以自动将视图移动到纵向模式,以便在该按钮中调用此方法
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
当条件发生变化时,您需要调用以使系统调用您的
supportedInterfaceOrientations
。如果您想将应用程序的主视图锁定为纵向视图,但想在横向视图中打开弹出视图,并且像我一样使用tabBarController作为rootViewController,您可以在AppDelegate上使用此代码
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UITabBarController *tabBarController;
@end
它工作得很好
在要在横向视图中显示的viewController中,只需使用以下命令:
- (NSUInteger) supportedInterfaceOrientations {
if (self.modeHeadsUp) {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
} else {
return UIInterfaceOrientationMaskAll;
}
}
- (BOOL) shouldAutorotate {
return TRUE;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate {
return YES;
}
唯一对我有效的方法是呈现虚拟模态视图控制器
UIViewController* dummyVC = [[UIViewController alloc] init];
dummyVC.view = [[UIView alloc] init];
[self presentModalViewController:dummyVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
当模态视图控制器被解除时,您的VC将被要求更新界面方向
奇怪的是,当推/弹出具有不同支持界面方向的子视图控制器(在iOS 6.1和7.0上测试)时,UINavigationController正是这样做的。定位问题的完美解决方案..ios7及更早版本
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:@"orientation"];
这在
Xcode
6和5上对我有效
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait);
}
可以工作,但必须在视图控制器中返回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:此解决方案也适用于所有模拟器。基本UINavigationController应具有以下回调,以便子项可以决定它们想要的方向
-(NSUInteger)supportedInterfaceOrientations {
UIViewController *topVC = self.topViewController;
return topVC.supportedInterfaceOrientations;
}
-(BOOL)shouldAutorotate {
UIViewController *topVC = self.topViewController;
return [topVC shouldAutorotate];
}
如果您只需要纵向模式,在iOS 9(Xcode 7)中,您可以:
- 去Info.plist
- 选择“支持的接口方向”项
- 删除“横向(左主按钮)”和“横向(右主按钮)”
我遇到的问题与你类似。我需要为一些屏幕锁定设备方向(如登录),并允许在其他屏幕上旋转 在做了一些更改并遵循以下一些答案后,我通过以下方式完成了:
- 在项目的Info.plist中启用所有方向
- 在需要设备不旋转的视图控制器中禁用方向,如我的案例中的登录屏幕。我需要在此VC中重写
方法:shouldAutorotate
-(BOOL)应自动旋转{
返回否;
}
希望这对你有用
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
属性如果您有一个UIViewController,它应该保持在纵向模式,只需添加这个覆盖,就可以全部设置好
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
最好的部分是显示此视图时没有动画,它只是已经处于正确的方向。此解决方案允许您通过临时覆盖
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)
这里是iOS 7、8、9、10如何将应用程序方向更改为当前相反方向的完整工作示例 目标-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()
}
这对我很有效
NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
对于像我这样努力让@Sunny Shah接受ipad工作的人来说。您需要在项目设置中设置“需要全屏”复选框。请注意,这将阻止你的应用程序在多任务模式下工作,这可能是可以接受的,也可能是不可以接受的
2020年Swift 5:
override var supportedInterfaceOrientations:UIInterfaceOrientationMask {
return .portrait
}
我不太清楚您的建议是什么,但在iOS7中,shouldAutorotateToInterfaceOrientation似乎被弃用,取而代之的是shouldAutorotate,我已经实现了它。对不起,我的错误。仅使用shouldAutorotate和-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientati