一、几个核心的方法
1.1屏幕旋转方向
- (BOOL)shouldAutorotate//是否支持旋转屏幕{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations//支持哪些方向{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation//默认显示的方向{
return UIInterfaceOrientationPortrait;
}
方法调用有限制
官方原文:
1.也就是只有在window 的 rootcontroller 或者 window最上层prensented controller里面使用上面三个函数,用户旋转的时候才能得到调用。
2.只有shouldAutorotate 返回YES时其他两个函数才能得到调用,返回为NO的时候默认为
UIInterfaceOrientationMaskPortrait
方向。
因此要控制某个界面旋转只能在windows 的控制器里面,覆盖以上上个方法,并在supportedInterfaceOrientations
获取你需要旋转的控制器的方向。具体的使用代码下面有讨论根控制器分别为UITabBarController
与UINavigationController
的情况。
1.2 代码切换屏幕方向
//代码切换屏幕方向
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
1.3 显示旋转横屏时消失的状态栏
在info.plist
文件中将 View controller-based status bar appearance
设置为NO
在application:didFinishLaunchingWithOptions:
中添加下面代码
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
如此之后你就会发现消失的状态条又乖乖的回来了。
1.4 屏幕旋转的几个代理方法
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration NS_DEPRECATED_IOS(2_0,8_0, "Implement viewWillTransitionToSize:withTransitionCoordinator: instead") __TVOS_PROHIBITED;
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation NS_DEPRECATED_IOS(2_0,8_0) __TVOS_PROHIBITED;
方便控制器对屏幕旋转做出相应的响应:
1.5 监听设备的旋转
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onDeviceOrientationChange) name:UIDeviceOrientationDidChangeNotification object:nil];
-(void)onDeviceOrientationChange
{
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(orientation)) {
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}else if (orientation==UIDeviceOrientationPortrait){
[self.collectionView reloadData];
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}
}
二、系统支持横屏顺序
(1) 默认读取plist里面设置的方向(优先级最高)等同于Xcode Geneal设置里面勾选
只要在plist或者General设置了单一方向,在工程里面的任何代码都会失效。所以想要旋转屏幕,必须让你的工程支持所旋转的方向。
(但是这里还有一种方式是把当前控制器的View或者view.layer做transform旋转,但是我认为这并不是真正的旋转屏幕,一点可以证明的就是:状态条并不随着旋转)
(2)application window设置的级别次之
(3)然后是UINavigationcontroller
(4)级别最低的是viewcontroller
三、设置部分控制器旋转
具体需求描述如下:
要求app 推入到TGLivePlayController时,(1)用户点击视频全屏/退出全屏书时,自定义播放view可以做出响应的全屏/16:9显示 (2)用户退出TGLivePlayController时,app自动切换到竖屏状态。
3.1 根控制器为UINavigationController
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationPortrait;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
UIViewController *vc = self.visibleViewController;
if([vc isKindOfClass:[TGLiveVideoController class]]){
return [vc supportedInterfaceOrientations];
}else{
return UIInterfaceOrientationMaskPortrait;
}
}
-(BOOL)shouldAutorotate{
UIViewController *vc = self.visibleViewController;
return [vc shouldAutorotate];
//也可以这样写只在指定的vc里面响应,只是这样在退出指定的控制器时不能在willdisappear里面还原竖屏。
if([vc isKindOfClass:[TGLiveVideoController class]]){
return [vc supportedInterfaceOrientations];
}
return NO;
}
3.2 根视图控制器为TabBarController
创建NavigationController和TabBarVontroller的category
这里注意不能在tabbarcontroller的类里写旋转方法 否则以下方法会无效
UITabBarController+autoRotate.h
#import <UIKit/UIKit.h>
@interface UITabBarController (autoRotate)
-(BOOL)shouldAutorotate;
-(NSUInteger)supportedInterfaceOrientations;
@end
UITabBarController+autoRotate.m
#import "UITabBarController+autoRotate.h"
@implementation UITabBarController (autoRotate)
-(BOOL)shouldAutorotate{
return [self.selectedViewController shouldAutorotate];
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return [self.selectedViewController supportedInterfaceOrientations];
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
@end
UINavigationController+autoRotate.h
@interface UINavigationController (autoRotate)
-(BOOL)shouldAutorotate;
-(NSUInteger)supportedInterfaceOrientations;
@end
UINavigationController+autoRotate.m
-(BOOL)shouldAutorotate{
return [self.selectedViewController shouldAutorotate];
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return [self.selectedViewController supportedInterfaceOrientations];
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
3.3 控制器代码
TGLiveVideoController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self LVSetUpNavItem];
[self LVSetUpSubviews];
}
-(void)LVSetUpNavItem{
self.navigationItem.leftBarButtonItem = nil;//移除原有的统一定制的返回键
UIButton *LeftItem = [UIButton new];
LeftItem.frame = CGRectMake(0, 0, 24, 24);
[LeftItem.imageView setContentMode:UIViewContentModeCenter];
[LeftItem setImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
[LeftItem setBackgroundImage:[UIImage imageNamed:@"nav_fanhui"] forState:UIControlStateNormal];
[LeftItem addTarget:self action:@selector(LVbackBtnClick) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *customLeftItem = [[UIBarButtonItem alloc] initWithCustomView:LeftItem];
self.navigationItem.leftBarButtonItem = customLeftItem;
}
#pragma mark - 替换统一生成的返回键事件
-(void)LVbackBtnClick{
//先旋转后退回
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[self.navigationController popViewControllerAnimated:YES];
}
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
CGFloat videoWidth = kScreenWidth;
CGFloat videoHeight = _isFullScreen ? self.view.bounds.size.height : kScreenWidth / 16.0f * 9.0f;
[self.player setPreviewFrame:CGRectMake(0, 0, videoWidth, videoHeight)];
CGFloat btnW = 60.0f;
CGFloat btnH = 40.0f;
CGFloat btnX = CGRectGetMaxX(self.player.previewView.frame) - btnW;
CGFloat btnY = CGRectGetMaxY(self.player.previewView.frame) - btnH;
self.btnFullScreen.frame = CGRectMake(btnX, btnY, btnW, btnH);
}
-(BOOL)shouldAutorotate{
return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
#pragma mark - 旋转代理事件
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration{
_isFullScreen = NO;
//横屏情况
if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
toInterfaceOrientation == UIInterfaceOrientationLandscapeRight){
_isFullScreen = YES;
}
self.btnFullScreen.selected = _isFullScreen;
}
#pragma mark - 全屏点击
-(void)btnFullScreenClick:(UIButton *)sender{
BOOL state = !self.isFullScreen;
if(state){
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}else{
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
}
参考文献: