這段時間在做跟視頻有關的工作,視頻嘛,肯定不是小窗口播放,在手機上播放視頻肯定就是最大屏幕利用率啦,這就會用到全屏播放--也就是旋轉屏幕。
下面我就來介紹下我自己的解決方案:
先說一個別我在網上查到的資料,這里給大家更正一個問題就是要設置app的橫屏還是豎屏在Xcode里面有很多設置的
系統支持橫屏順序
application window設置
默認讀取plist里面設置的方向(優先級最高)等同于Xcode Geneal設置里面勾選
然后是UINavigationcontroller
級別最低的是viewcontroller
知道了這個順序做橫屏就變得很容易了
application支持所有
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskAll;//支持所有方向
}
UINavigationcontroller支持豎屏
- (BOOL)shouldAutorotate//是否支持旋轉屏幕{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations//支持哪些方向{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation//默認顯示的方向{
return UIInterfaceOrientationPortrait;
}
viewcontroller支持橫屏(pushmodel出來)
- (BOOL)shouldAutorotate//是否支持旋轉屏幕{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations//支持哪些方向{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation//默認顯示的方向{
return UIInterfaceOrientationLandscapeLeft;
}
說明一點,只要在plist或者General設置了支持的方向
表示其界面支持的自動旋轉的方向
所以想要旋轉屏幕,必須讓你的工程支持所旋轉的方向。(但是這里還有一種方式是把當前控制器的View或者view.layer做transform旋轉,但是我認為這并不是真正的旋轉屏幕,一點可以證明的就是:狀態條并不隨著旋轉)
其實這個優先級跟你的window的rootViewcontroller有關系,如果rootViewcontroller是UITabbarViewontroller,那么tabbar就類似前面所說的UINavigationcontroller,在iOS6之后好多方法發生了改變,之前的一個屏幕旋轉的方法就失效了,更改位上面的方法。
其實屏幕旋轉在手機里面有設置,上拉菜單就會有關閉屏幕旋轉的方式,但是大家都知道好多應用在關閉屏幕旋轉的時候也可以進行屏幕旋轉---通過某一個按鈕的事件來觸發,這就是強制旋轉(前提依然是你的工程設置支持你所要旋轉的方向)
一般的不需要旋轉的程序只需要勾選第一個就可以了。
由于軟件需要我勾選的是第一個和第四個,在Coding之前我要告訴大家一個細節:在iOS8之后,屏幕旋轉到橫向的時候,狀態條就會默認隱藏,我覺得蘋果是默認讓你獲得最大的顯示區域,但是對于我這個輕微強迫癥的人來說,橫屏也要顯示狀態條,以為看著那個綠色的電池比較舒服(O(∩_∩)O),具體的操作方法就是:
在info.plist文件中將 View controller-based status bar appearance
設置為NO
在application:didFinishLaunchingWithOptions:
中添加下面代碼
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
如此之后你就會發現消失的狀態條有乖乖的回來了。
接下來就是Coding了:
翻閱各大網站和論壇我總結了好幾種方式,但是大同小異的旋轉屏幕的代碼,以供參考:
支持ARC版本:(這個方法可以使用,并且可以通過蘋果的審核,已經有人使用并審核通過了)
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
SEL selector = NSSelectorFromString(@"setOrientation:");
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:[UIDevice currentDevice]];
int val = UIInterfaceOrientationLandscapeRight;//這里可以改變旋轉的方向
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
或者
//但是注意這個方法必須在general里面設置支持鎖旋轉的方向,否則就是強行旋轉,會導致程序崩潰,而且不會有崩潰日志,很難發現崩潰在哪里,所以使用這個方法的時候一定要注意設置支持的方向。
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIDeviceOrientationPortrait] forKey:@"orientation"];
不支持ARC版本
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
[[UIDevice currentDevice] performSelector:@selector(setOrientation:)
withObject:(id)UIInterfaceOrientationLandscapeRight];
}
還有一點就是如何判斷當前屏幕的方向:可以根據電源的現實方向來判斷,蘋果提供了這一方法
NSInteger i = [[UIApplication sharedApplication] statusBarOrientation];
if (i == UIInterfaceOrientationLandscapeRight){
//在這里可以寫相應的代碼
}
有些人可能想要監聽屏幕的自動旋轉:
1.注冊UIApplicationDidChangeStatusBarOrientationNotification通知(舉例:在一個viewcontroller類的viewdidload中注冊該通知),示例代碼如下:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:)name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
- (void)statusBarOrientationChange:(NSNotification *)notification{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationLandscapeRight) // home鍵靠右{
//
}
if (orientation ==UIInterfaceOrientationLandscapeLeft) // home鍵靠左 {
//
}
if (orientation == UIInterfaceOrientationPortrait){
//
}
if (orientation == UIInterfaceOrientationPortraitUpsideDown){
//
}
}
注意這種方式監聽的是StatusBar也就是狀態欄的方向,所以這個是跟你的布局有關的,你的布局轉了,才會接到這個通知,而不是設備旋轉的通知。當我們關注的東西和布局相關而不是純粹設備旋轉,我們使用上面的代碼作為實現方案比較適合。
2.注冊UIDeviceOrientationDidChangeNotification通知(舉例:我們同樣在一個viewcontroller類的viewdidload中注冊該通知),示例代碼如下:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientChange:)name:UIDeviceOrientationDidChangeNotification object:nil];
- (void)orientChange:(NSNotification *)noti
{
NSDictionary* ntfDict = [noti userInfo];
UIDeviceOrientation orient = [UIDevice currentDevice].orientation;
/*
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom
UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top
UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right
UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left
UIDeviceOrientationFaceUp, // Device oriented flat, face up
UIDeviceOrientationFaceDown // Device oriented flat, face down */
switch (orient)
{
case UIDeviceOrientationPortrait:
break;
case UIDeviceOrientationLandscapeLeft:
break;
case UIDeviceOrientationPortraitUpsideDown:
break;
case UIDeviceOrientationLandscapeRight:
break;
default:
break;
}
}
注意到這種方式里面的方向還包括朝上或者朝下,很容易看出這個完全是根據設備自身的物理方向得來的,當我們關注的只是物理朝向時,我們通常需要注冊該通知來解決問題(另外還有一個加速計的api,可以實現類似的功能,該api較底層,在上面兩個方法能夠解決問題的情況下建議不要用,使用不當性能損耗非常大)。
補充:
利用runtime方法:
UIInterfaceOrientation ifo=[[UIApplication sharedApplication] statusBarOrientation];
((void(*)(id,SEL,UIInterfaceOrientation,BOOL))objc_msgSend)([UIDevice currentDevice],NSSelectorFromString([NSString stringWithFormat:@"set%@:animated:",tmpStr]),ifo,NO);
補充:參考鏈接http://www.cocoachina.com/ios/20180323/22747.html
歡迎關注我的微博和博客。