首先说一下需求吧!app整体竖屏不支持旋转,只有在webview播放视屏的时候横屏(不是自动旋转哦)。刚开始拿到需求的时候以为很简单。但是由于项目之前其实已经有一部分这块的逻辑了,所以就想着捡现成的。网上百度了很多,思路上基本上都是调用系统监听打开全屏(UIWindowDidResignKeyNotification、UIWindowDidBecomeVisibleNotification)、退出全屏(UIWindowDidBecomeHiddenNotification)从这里开始有一点分支一个是调用系统那一套旋转方法
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window ;
- (BOOL)shouldAutorotate;
- (UIInterfaceOrientationMask)supportedInterfaceOrientations;
-(UIInterfaceOrientation)bl_preferredInterfaceOrientationForPresentation;
一个是自己对window做旋转,也就是在相应的监听方法里调用旋转方法例如:
//将要进入全屏
UIApplication *application=[UIApplication sharedApplication];
[applicationsetStatusBarOrientation: UIInterfaceOrientationLandscapeRight];
application.keyWindow.transform=CGAffineTransformMakeRotation(M_PI/2);
CGRect frame = [UIScreen mainScreen].bounds;
application.keyWindow.bounds=CGRectMake(0,0, frame.size.height, frame.size.width);
//退出全屏
UIApplication *application=[UIApplication sharedApplication];
[applicationsetStatusBarOrientation: UIInterfaceOrientationLandscapeRight];
CGRect frame = [UIScreen mainScreen].bounds;
application.keyWindow.bounds=CGRectMake(0,0, frame.size.width, frame.size.height);
application.keyWindow.transform=CGAffineTransformMakeRotation(M_PI * 2);
先说一下这个思路吧 首先这个监听事件就不是那么准确,别的事件是有可能触发这个监听的。这样就会造成一些界面错乱的情况。
之后我就再想能不能让h5那边给一个事件告诉我全屏 和 退出全屏的时机。后来跟项目经理沟通后,感觉指望不上。
好吧,这条路走不通。打开播放视频的视图层级看了以后,发现了一个AVFullScreenViewController。度娘了以后知道这是一个苹果没有暴露给我们使用的视频类控制器。当时的想法是分类运用runtime,来对这个控制器做一些操作。结果发现拿不到这个控制器。真是尴尬。后来查到了贝聊科技的BLLandscape。这个思路就有点类似了。不过他是对UIViewcontroller进行的分类,关键在于怎么区分出AVFullScreenViewController。看了一下源码:
- (BOOL)checkSelfNeedLandscape{ NSProcessInfo *processInfo = [NSProcessInfo processInfo]; NSOperatingSystemVersion operatingSytemVersion = processInfo.operatingSystemVersion;if(operatingSytemVersion.majorVersion == 8) { NSString *className = NSStringFromClass(self.class);if([@[@"AVPlayerViewController", @"AVFullScreenViewController", @"AVFullScreenPlaybackControlsViewController"] containsObject:className]) {returnYES; }if([self isKindOfClass:[UIViewController class]] && [self childViewControllers].count && [self.childViewControllers.firstObject isKindOfClass:NSClassFromString(@"AVPlayerViewController")]) {returnYES; } }elseif(operatingSytemVersion.majorVersion == 9){ NSString *className = NSStringFromClass(self.class);if([@[@"WebFullScreenVideoRootViewController", @"AVPlayerViewController", @"AVFullScreenViewController"] containsObject:className]) {returnYES; }if([self isKindOfClass:[UIViewController class]] && [self childViewControllers].count && [self.childViewControllers.firstObject isKindOfClass:NSClassFromString(@"AVPlayerViewController")]) {returnYES; } }elseif(operatingSytemVersion.majorVersion == 10){if([self isKindOfClass:NSClassFromString(@"AVFullScreenViewController")]) {returnYES; } }returnNO;}
可能是系统版本的差异性吧,[self isKindOfClass:NSClassFromString(@"AVFullScreenViewController")]这段代码并没有用。直接上代码吧!
给UIViewcontroller建一个分类:
#import "UIViewController+Landscape.h"
#import
@implementation UIViewController (Landscape)
+ (void)load{
staticdispatch_once_tonceToken;
dispatch_once(&onceToken, ^{
Classclass = [selfclass];
SELoriginalSelector =@selector(viewWillAppear:);
SELswizzledSelector =@selector(bl_viewWillAppear:);
MethodoriginalMethod =class_getInstanceMethod(class, originalSelector);
MethodswizzledMethod =class_getInstanceMethod(class, swizzledSelector);
BOOLsuccess =class_addMethod(class, originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));
if(success) {
class_replaceMethod(class, swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));
}else{
method_exchangeImplementations(originalMethod, swizzledMethod);
}
SELoriginalSelector1 =@selector(viewWillDisappear:);
SELswizzledSelector1 =@selector(bl_viewWillDisappear:);
MethodoriginalMethod1 =class_getInstanceMethod(class, originalSelector1);
MethodswizzledMethod1 =class_getInstanceMethod(class, swizzledSelector1);
BOOLsuccess1 =class_addMethod(class, originalSelector1,method_getImplementation(swizzledMethod1),method_getTypeEncoding(swizzledMethod1));
if(success1) {
class_replaceMethod(class, swizzledSelector1,method_getImplementation(originalMethod1),method_getTypeEncoding(originalMethod1));
}else{
method_exchangeImplementations(originalMethod1, swizzledMethod1);
}
});
}
- (void)bl_viewWillAppear:(BOOL)animated{
[selfbl_viewWillAppear:animated];
if ([[[UIApplication sharedApplication].keyWindow.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"MPInlineVideoFullscreenViewController")] ||
[[[UIApplication sharedApplication].keyWindow.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"AVFullScreenViewController")]){
UIApplication *application=[UIApplication sharedApplication];
application.keyWindow.transform=CGAffineTransformMakeRotation(M_PI/2);
CGRect frame = [UIScreen mainScreen].bounds;
application.keyWindow.bounds=CGRectMake(0,0, frame.size.height, frame.size.width);
}
}
- (void)bl_viewWillDisappear:(BOOL)animated{
[self bl_viewWillDisappear:animated];
if ([[[UIApplication sharedApplication].keyWindow.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"MPInlineVideoFullscreenViewController")] ||
[[[UIApplication sharedApplication].keyWindow.rootViewController presentedViewController] isKindOfClass:NSClassFromString(@"AVFullScreenViewController")]){
UIApplication *application=[UIApplication sharedApplication];
CGRect frame = [UIScreen mainScreen].bounds;
application.keyWindow.bounds=CGRectMake(0,0, frame.size.width, frame.size.height);
application.keyWindow.transform=CGAffineTransformMakeRotation(M_PI * 2);
}
}
@end
本来准备用系统那一套旋转方法的,但是在不同系统上面不同表现。实在摸不清头脑,放弃了。如果有大佬知道原因的话望指点一二。第一次写,有什么问题,麻烦各位大佬指正!