简介
-
工程绝大多数界面只支持竖屏(大多数)
-
其中的拍照界面只支持横屏(少数)
工程配置
- 理论上,工程配置是其效果的。通常的应用会配置为只支持竖屏。
屏幕旋转在大多数情况下是个副作用,所以整体配置上需要禁止旋转。
-
问题: 这样设置不起效果!!!
原因: Info文件中增加了内容,没有改全。
代码配置
- 工程Plist配置影响了初始化,在代码中可以进行修改覆盖。修改的地方在
AppDelegate
,只是以代理回调方法的形式存在,设置起来并不方便。
*AppDelegate
只有一个,并且系统提供了类似单例的访问方法,这为修改带来了方便。
-
与工程配置相比,代码配置更加灵活。可以在特定的时候进行修改。
-
在
AppDelegate.h
中提供一个属性供外部设置,修改。
@interface AppDelegate : UIResponder <UIApplicationDelegate>
// 与SceneDelegate中的window是同一个;
// 很多第三方库,比如SVProgressHUD要用到;
// 自己以view的方式做弹窗也要用到;
@property (nonatomic, strong) UIWindow *window;
// NO:只支持竖屏;YES:支持横屏(Home键在右)
@property (nonatomic, assign) BOOL isLandscapeRight;
@end
- 在
AppDelegate.m
中修改配置
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// 默认不支持横屏,只支持竖屏
self.isLandscapeRight = NO;
return YES;
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
// 大多数情况只支持竖屏,少部分情况只支持横屏(Home键向右)
if (self.isLandscapeRight) {
return UIInterfaceOrientationMaskLandscapeRight;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
旋转手机
-
在
AppDelegate.m
中只是设置了xxxMask
,代表了允许手机旋转的方向范围,并没有让手机实际旋转。 -
旋转手机的
API
在UIDevice
中,可是苹果并没有开发这个API
,目前可以通过KVO
的方式间接调用。
这真的是很扯淡的事情。
iOS强制改变物理设备方向的进阶方法
// 旋转手机
+ (void)forceToOrientation:(UIDeviceOrientation)orientation {
NSNumber *orientationTarget = [NSNumber numberWithInteger:orientation];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
}
- 实现旋转:要求Mask和实际的旋转动作相配套。不然的话没有效果。
比如,你在
AppDelegate.m
设置只能竖屏的Mask,但是你却要求横屏向右旋转,结果当然是没效果。(自相矛盾啊)
// 旋转到横屏
+ (void)rotateToLandscapeRight {
// 先设置Mask
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.isLandscapeRight = YES;
// 然后旋转手机;方向需要在Mask的范围之内
[PDADevice forceToOrientation:UIDeviceOrientationLandscapeRight];
}
// 旋转到竖屏
+ (void)rotateToPortrait {
// 先设置Mask
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.isLandscapeRight = NO;
// 然后旋转手机;方向需要在Mask的范围之内
[PDADevice forceToOrientation:UIDeviceOrientationPortrait];
}
调用时机
由于绝大多数页面只需要竖屏就可以了,这个只要在工程配置的地方配置一下就行。
对于需要横屏的页面,可以在viewWillAppear
中设置为横屏,然后在viewWillDisappear
中设置为竖屏就可以了。
- (void)viewWillAppear:(BOOL)animated {
/*
* 设置横屏
*/
[PDADevice rotateToLandscapeRight];
}
- (void)viewWillDisappear:(BOOL)animated {
/*
* 设置竖屏
*/
[PDADevice rotateToPortrait];
}
参考文章
iOS 不勾选设置工程Landscape,实现某个界面强制横屏
失效的屏幕旋转方法
- 很多文章都说重写下面几个方法,可以实现屏幕旋转。可是实际试过之后才知道并不可行。
- (BOOL)shouldAutorotate {
return NO; // 注意:如果是只支持一种,比如只支持横屏,这里需要设置为NO;YES的至少需要两种或者以上的Mask才行。
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeRight;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight;
}
- 之所以要通过重写
getter
方法的方式来实现修改的目的,是因为UIViewController
的这3个属性是只读的。
// New Autorotation support.
@property(nonatomic, readonly) BOOL shouldAutorotate API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
@property(nonatomic, readonly) UIInterfaceOrientationMask supportedInterfaceOrientations API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
// Returns interface orientation masks.
@property(nonatomic, readonly) UIInterfaceOrientation preferredInterfaceOrientationForPresentation API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
-
如果是
present
出来的界面,上面的设置是可以起效果的。 -
如果是
Navigation Controller
管理,push(show)
出来的界面,上面那样设置是不起效果的。因为Navigation Controller
是容器,UIViewContainer
是容器里的物品。容器和物品的方向要一致才能起效果。
所以,导致大部分时候,上面这些代码不起作用,估计大概率的原因是两者不匹配导致的。
吐槽
-
旋转屏幕,固定屏幕朝向,直观上应该是很简单的一个功能,但是实际用下来,却要用到黑科技
(KVO)
。这不得不让人吐槽苹果真不厚道。 -
就算是通过属性设置,却提供好几个“只读”属性,并且要好几个属性配合起来才行。
-
更夸张的是设定当前
UIViewContainer
的朝向,还竟然要考虑容器Navigation Controller
的朝向,还要保证两者一致才有可能起效果。 -
这样搞,要么就是存心不让人使用改变屏幕朝向的API;要么就是设计这些个API的人是蠢货。苹果工程师出蠢货也不是一两个例子了。
网友评论