iOS屏幕旋轉(zhuǎn)與鎖屏的示例代碼
在做視頻開發(fā)時(shí)遇到屏幕旋轉(zhuǎn)問(wèn)題,其中涉及到 StatusBar、 UINavigationController、UITabBarController 、UIViewcontroller 。
在設(shè)備鎖屏下的整體效果圖

iOS-旋轉(zhuǎn).gif
主要涉及以下4點(diǎn):
- 橫豎屏的旋轉(zhuǎn)
- 屏幕旋轉(zhuǎn)相應(yīng)改變視圖位置
- 旋轉(zhuǎn)時(shí)狀態(tài)欄的隱藏與顯示
- 鎖屏
1、橫豎屏旋轉(zhuǎn)
第1步:
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
// NSLog(@"0000000---------%@",NSStringFromClass([[self topViewController] class]));
// if ([NSStringFromClass([[self topViewController] class]) isEqualToString:@"FirstViewController"]) {
// //橫屏
// return UIInterfaceOrientationMaskLandscapeRight;
// }
// //豎屏
// return UIInterfaceOrientationMaskPortrait;
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
if(self.window.rootViewController){
//取出當(dāng)前顯示的控制器
UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController];
//按當(dāng)前控制器支持的方向確定旋轉(zhuǎn)方向(將旋轉(zhuǎn)方向重新交給每個(gè)控制器自己控制)
NSLog(@"%s, line = %d",__FUNCTION__,__LINE__);
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
//獲取界面最上層的控制器
//- (UIViewController*)topViewController {
// NSLog(@"%s, line = %d",__FUNCTION__,__LINE__);
// return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
//}
//一層一層的進(jìn)行查找判斷
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
NSLog(@"%s, line = %d",__FUNCTION__,__LINE__);
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
NSLog(@"Tabbar:%@",NSStringFromClass([tabBarController.selectedViewController class]));
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* nav = (UINavigationController*)rootViewController;
NSLog(@"nav:%@",NSStringFromClass([nav.visibleViewController class]));
return [self topViewControllerWithRootViewController:nav.visibleViewController];
} else if (rootViewController.presentedViewController) {
NSLog(@"present:%@",NSStringFromClass([rootViewController.presentationController class]));
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
NSLog(@"root:%@",rootViewController);
return rootViewController;
}
}
代碼中通過(guò) -(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window 方法將控制器交給自己控制,該方法默認(rèn)值為 Info.plist 中配置的 Supported interface orientations 項(xiàng)的值。
第2步:在各控制器設(shè)置支持的方向
//是否允許旋轉(zhuǎn)(默認(rèn)允許)
- (BOOL)shouldAutorotate {
return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
//允許旋轉(zhuǎn)的方向
return UIInterfaceOrientationMaskAll;
}
其中 - supportedInterfaceOrientations 方法在 iPad 中默認(rèn)取值為 UIInterfaceOrientationMaskAll ,即默認(rèn)支持所有屏幕方向;而 iPhone 跟 iPod Touch 的默認(rèn)取值為 UIInterfaceOrientationMaskAllButUpsideDown ,即支持除豎屏向下以外的三個(gè)方向。
在設(shè)備屏幕旋轉(zhuǎn)時(shí),系統(tǒng)會(huì)調(diào)用 - shouldAutorotate 方法檢查當(dāng)前界面是否支持旋轉(zhuǎn),只有 - shouldAutorotate 返回 YES 的時(shí)候, - supportedInterfaceOrientations 方法才會(huì)被調(diào)用,以確定是否需要旋轉(zhuǎn)界面。
這個(gè)是 TabbarController 中設(shè)置的,它會(huì)影響關(guān)聯(lián)的 UIViewController 的支持方向,需要在 UIViewController 中進(jìn)一步設(shè)置
//此方法來(lái)控制能否橫豎屏 控制鎖屏
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSLog(@"%s, line = %d",__FUNCTION__,__LINE__);
UIInterfaceOrientationMask inter;
if (_lockScreen) {
switch (_lockOrientation) {
case 1:
inter = UIInterfaceOrientationMaskPortrait;
break;
case 2:
inter = UIInterfaceOrientationMaskPortraitUpsideDown;
break;
case 3:
inter = UIInterfaceOrientationMaskLandscapeRight;
break;
case 4:
inter = UIInterfaceOrientationMaskLandscapeLeft;
break;
default:inter = UIInterfaceOrientationMaskAll;
break;
}
} else {
inter = UIInterfaceOrientationMaskAll;
}
//支持全部方向
return inter;
}
第3步:強(qiáng)制轉(zhuǎn)換控制器方向
- (void)setInterOrientation:(UIInterfaceOrientation)orientation {
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 = orientation;
// 從2開始是因?yàn)? 1 兩個(gè)參數(shù)已經(jīng)被selector和target占用
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
}
這樣就可以完成橫豎屏的切換。
2、屏幕旋轉(zhuǎn)相應(yīng)改變視圖位置
這里先擴(kuò)展 UIDeviceOrientation & UIInterfaceOrientation 的知識(shí)
UIDeviceOrientation 設(shè)備的物理方向
UIDeviceOrientation 即我們手持的移動(dòng)設(shè)備的 Orientation ,是一個(gè)三圍空間,有六個(gè)方向,通過(guò) [UIDevice currentDevice].orientation 獲取當(dāng)前設(shè)備的方向。
typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top 豎屏向下,即頭在下,Home 鍵在上
UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right 橫屏頭在左,Home鍵在右
UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left 橫屏頭在右,Home鍵在左
UIDeviceOrientationFaceUp, // Device oriented flat, face up
UIDeviceOrientationFaceDown // Device oriented flat, face down
} ;
UIInterfaceOrientation 界面的顯示方向
UIInterfaceOrientation 即我們看到的視圖的 Orientation ,可以理解為 statusBar 所在的方向,是一個(gè)二維空間,有四個(gè)方向, 通過(guò) [UIApplication sharedApplication].statusBarOrientation 即狀態(tài)欄的方向獲取當(dāng)前界面方向。
// Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
// This is because rotating the device to the left requires rotating the content to the right.
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
}
UIInterfaceOrientationMask 支持的方向
// iOS 6 之后用于控制界面的枚舉值
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
}
由上可以發(fā)現(xiàn):
iOS 6 及之后版本使用的 UIInterfaceOrientationMask 類型來(lái)控制屏幕屏幕方向,該類型也新增加了幾個(gè)枚舉取值,可用一個(gè)枚舉取值來(lái)代表多個(gè)屏幕方向,使用起來(lái)更方便。
注意在 UIInterfaceOrientation 中有注釋
Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
This is because rotating the device to the left requires rotating the content to the right,大意是界面的左轉(zhuǎn)相當(dāng)于設(shè)備的右轉(zhuǎn),如果設(shè)備向左轉(zhuǎn)時(shí)就需要內(nèi)容(即界面)向右轉(zhuǎn)。即:
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
下面還會(huì)舉例說(shuō)明。
其實(shí) UIDeviceOrientation 與 UIInterfaceOrientation 是兩個(gè)互不相干的屬性,通常情況下會(huì)一起出現(xiàn),在這里正好利用此特性在屏幕旋轉(zhuǎn)后進(jìn)行重新布局。
第1步:監(jiān)聽 UIDeviceOrientationDidChangeNotification 狀態(tài)
//監(jiān)聽設(shè)備旋轉(zhuǎn) 改變 視圖 對(duì)應(yīng)位置
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil];
//用來(lái)控制橫豎屏?xí)r調(diào)整視圖位置
- (void)deviceOrientationDidChange
{
[self isPortrait];
}
第2步:重新布局
if (_interOrientation == UIInterfaceOrientationPortrait || _interOrientation == UIInterfaceOrientationPortraitUpsideDown) {
self.top.constant = 145;
self.bottom.constant = 210;
} else if (_interOrientation == UIInterfaceOrientationLandscapeRight || _interOrientation == UIInterfaceOrientationLandscapeLeft) {
self.top.constant = 40;
self.bottom.constant = 50;
}
例如:豎屏轉(zhuǎn)橫屏
界面豎屏 UIInterfaceOrientationPortrait ->橫屏 UIInterfaceOrientationLandscapeRight ,設(shè)備方向 UIDeviceOrientationPortrait -> UIDeviceOrientationLandscapeLeft ,在設(shè)備發(fā)生變化這個(gè)過(guò)程觸發(fā) UIDeviceOrientationDidChangeNotification 監(jiān)聽,然后進(jìn)行重新布局。
3、旋轉(zhuǎn)時(shí)狀態(tài)欄的隱藏與顯示
這里只記述旋轉(zhuǎn)時(shí)狀態(tài)欄的變化,由豎屏想橫屏變化時(shí)狀態(tài)欄會(huì)消失。
//在需要的`UIViewController`設(shè)置是否隱藏
- (BOOL)prefersStatusBarHidden {
NSLog(@"%s, line = %d",__FUNCTION__,__LINE__);
return NO;
}
4、鎖屏
鎖屏?xí)r,不管系統(tǒng)鎖屏是否關(guān)閉、Push 或 Present 返回后,界面依然保持不變。
第1步:設(shè)置鎖屏
- (IBAction)lockAction:(UIButton *)sender {
if (_lockScreen) {
_lockScreen = NO;
[sender setTitle:@"鎖定屏幕" forState:UIControlStateNormal];
} else {
_lockScreen = YES;
[sender setTitle:@"解開屏幕" forState:UIControlStateNormal];
}
_lockOrientation = _interOrientation;
}
第2步:繞過(guò)強(qiáng)轉(zhuǎn)
- (void)interfaceOrientation:(UIInterfaceOrientation)orientation
{
[self isPortrait];
//鎖屏情況下 不旋轉(zhuǎn)
if (!_lockScreen) {
[self setInterOrientation:orientation];
}
第3步:針對(duì) Push 或 Present 返回后
- (void)viewWillAppear:(BOOL)animated {
if (_lockScreen) {
//記錄返回時(shí)的界面狀態(tài)
[self setInterOrientation:_lockOrientation];
} else {
[self isPortrait];
}
}
5、 針對(duì)特定 UIViewController 方向的支持
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if ([NSStringFromClass([[self topViewController] class]) isEqualToString:@"FirstViewController"]) {
//橫屏
return UIInterfaceOrientationMaskLandscapeRight;
}
//豎屏
return UIInterfaceOrientationMaskPortrait;
}
最后的獻(xiàn)上 GitHub 代碼,還有2個(gè)小的 bug ,有興趣的朋友歡迎來(lái)探討。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS實(shí)現(xiàn)“搖一搖”與“掃一掃”功能示例代碼
本篇文章主要介紹了iOS實(shí)現(xiàn)“搖一搖”與“掃一掃”功能示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01
swift3.0實(shí)現(xiàn)圖片放大縮小動(dòng)畫效果
這篇文章主要為大家詳細(xì)介紹了swift3.0實(shí)現(xiàn)圖片放大縮小動(dòng)畫效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
iOS 高德地圖仿微信發(fā)送實(shí)時(shí)位置
這篇文章主要介紹了iOS 高德地圖仿微信發(fā)送實(shí)時(shí)位置,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
iOS開發(fā)之widget實(shí)現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了iOS開發(fā)之widget實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
iOS開發(fā)之?dāng)r截URL轉(zhuǎn)換成本地路由模塊URLRewrite詳解
這篇文章主要給大家介紹了關(guān)于iOS開發(fā)之?dāng)r截URL轉(zhuǎn)換成本地路由模塊URLRewrite的相關(guān)資料,這是最近在工作中遇到的一個(gè)需求,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來(lái)一起看看吧。2017-08-08
iOS實(shí)現(xiàn)圖片自動(dòng)切換效果
這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)圖片自動(dòng)切換效果,類似android畫廊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02

