目錄
一、最讓人糾結(jié)的三種枚舉
二皿桑、兩種屏幕旋轉(zhuǎn)的觸發(fā)方式
三、屏幕旋轉(zhuǎn)控制的優(yōu)先級(jí)
四蔬啡、開(kāi)啟屏幕旋轉(zhuǎn)的全局權(quán)限
五诲侮、開(kāi)啟屏幕旋轉(zhuǎn)的局部權(quán)限(視圖控制器)
六、實(shí)現(xiàn)需求:項(xiàng)目主要界面豎屏箱蟆,部分界面橫屏
七沟绪、默認(rèn)橫屏無(wú)效的問(wèn)題
八、關(guān)于旋轉(zhuǎn)后的適配問(wèn)題
九空猜、APP啟動(dòng)即全屏
一绽慈、最讓人糾結(jié)的三種枚舉
剛開(kāi)始接觸屏幕旋轉(zhuǎn)這塊知識(shí)的時(shí)候,最讓人抓狂的也許就是三種相關(guān)的枚舉類型了辈毯,它們就是UIDeviceOrientation久信、UIInterfaceOrientation、UIInterfaceOrientationMask漓摩。下面我們針對(duì)三種屬性進(jìn)行解析:
1. 設(shè)備方向:UIDeviceOrientation
UIDeviceOrientation是硬件設(shè)備(iPhone裙士、iPad等)本身的當(dāng)前旋轉(zhuǎn)方向,設(shè)備方向有7種(包括一種未知的情況)管毙,判斷設(shè)備的方向是以home鍵的位置作為參照的腿椎,我們來(lái)看一下它們?cè)谠创a中的定義如下:
//Portrait 表示縱向,Landscape 表示橫向夭咬。
typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
? ? UIDeviceOrientationUnknown,
? ? // Device oriented vertically, home button on the top
? ? UIDeviceOrientationPortraitUpsideDown,
? ? // Device oriented horizontally, home button on the right
? ? UIDeviceOrientationLandscapeLeft,? ? ?
? ? // Device oriented horizontally, home button on the left
? ? UIDeviceOrientationLandscapeRight,? ?
? ? // Device oriented flat, face up
? ? UIDeviceOrientationFaceUp,? ? ? ? ? ?
? ? // Device oriented flat, face down
? ? UIDeviceOrientationFaceDown? ? ? ? ? ?
} __TVOS_PROHIBITED;
設(shè)備方向只能取值,不能設(shè)置啃炸,
獲取設(shè)備當(dāng)前旋轉(zhuǎn)方向使用方法:[UIDevice currentDevice].orientation
監(jiān)測(cè)設(shè)備方向的變化,我們可以在Appdelegate文件中使用通知如下:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onDeviceOrientationDidChange)
? ? ? ? ? ? ? ? ? ? name:UIDeviceOrientationDidChangeNotification
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
- (BOOL)onDeviceOrientationDidChange{
? ? //獲取當(dāng)前設(shè)備Device
? ? UIDevice *device = [UIDevice currentDevice] ;
? ? //識(shí)別當(dāng)前設(shè)備的旋轉(zhuǎn)方向
? ? switch (device.orientation) {
? ? ? ? case UIDeviceOrientationFaceUp:
? ? ? ? ? ? NSLog(@"屏幕幕朝上平躺");
? ? ? ? ? ? break;
? ? ? ? case UIDeviceOrientationFaceDown:
? ? ? ? ? ? NSLog(@"屏幕朝下平躺");
? ? ? ? ? ? break;
? ? ? ? case UIDeviceOrientationUnknown:
? ? ? ? ? ? //系統(tǒng)當(dāng)前無(wú)法識(shí)別設(shè)備朝向卓舵,可能是傾斜
? ? ? ? ? ? NSLog(@"未知方向");
? ? ? ? ? ? break;
? ? ? ? case UIDeviceOrientationLandscapeLeft:
? ? ? ? ? ? NSLog(@"屏幕向左橫置");
? ? ? ? ? ? break;
? ? ? ? case UIDeviceOrientationLandscapeRight:
? ? ? ? ? ? NSLog(@"屏幕向右橫置");
? ? ? ? ? ? break;
? ? ? ? case UIDeviceOrientationPortrait:
? ? ? ? ? ? NSLog(@"屏幕直立");
? ? ? ? ? ? break;
? ? ? ? case UIDeviceOrientationPortraitUpsideDown:
? ? ? ? ? ? NSLog(@"屏幕直立南用,上下顛倒");
? ? ? ? ? ? break;
? ? ? ? default:
? ? ? ? ? ? NSLog(@"無(wú)法識(shí)別");
? ? ? ? ? ? break;
? ? }
? ? return YES;
}
2.頁(yè)面方向:UIInterfaceOrientation
UIInterfaceOrientation程序界面的當(dāng)前旋轉(zhuǎn)方向(可以設(shè)置),其源碼的定義如下:
// 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
? ? } __TVOS_PROHIBITED;
區(qū)別與UIDeviceOrientation,表示我們開(kāi)發(fā)的程序界面的方向使用UIInterfaceOrientation裹虫。
值得注意的是:
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
1
2
我們可以發(fā)現(xiàn)兩者的枚舉值大多是可以對(duì)應(yīng)上的肿嘲。只有左右旋轉(zhuǎn)的時(shí)候是UIInterfaceOrientationLandscapeLeft 與UIDeviceOrientationLandscapeRight相等,反之亦然筑公,這是因?yàn)橄蜃笮D(zhuǎn)設(shè)備需要旋轉(zhuǎn)程序界面右邊的內(nèi)容雳窟。
3.頁(yè)面方向:UIInterfaceOrientationMask
UIInterfaceOrientationMask是iOS6之后增加的一種枚舉,其源碼如下:
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),
} __TVOS_PROHIBITED;
我們知道UIDeviceOrientation與UIInterfaceOrientation的區(qū)別在于:前者是真實(shí)的設(shè)備方向匣屡,后者是頁(yè)面方向封救。
而UIInterfaceOrientation和UIInterfaceOrientationMask的區(qū)別是什么呢?其實(shí)觀察源碼捣作,我們就會(huì)發(fā)現(xiàn)這是一種為了支持多種UIInterfaceOrientation而定義的類型誉结。下面的示例將很好的說(shuō)明這點(diǎn):
在iOS6之后,控制單個(gè)界面的旋轉(zhuǎn)我們通常是下面三個(gè)方法來(lái)控制:
//方法1
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
//方法2
- (UIInterfaceOrientationMask)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
// Returns interface orientation masks.
//方法3
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
方法2的作用是設(shè)置當(dāng)前界面支持的所有方向券躁,所以返回值是UIInterfaceOrientationMask搓彻,更加方便的表達(dá)支持多方向旋轉(zhuǎn)的情況。
方法3的作用是設(shè)置進(jìn)入界面默認(rèn)支持的方向嘱朽,使用了返回值類型UIInterfaceOrientation旭贬,默認(rèn)進(jìn)入界面的方向是個(gè)確定的方向,所以使用UIInterfaceOrientation更適合搪泳。
二稀轨、兩種屏幕旋轉(zhuǎn)的觸發(fā)方式
我們開(kāi)發(fā)的App的,大多情況都是大多界面支持豎屏岸军,幾個(gè)特別的界面支持旋轉(zhuǎn)橫屏奋刽,兩種界面相互切換,觸發(fā)其旋轉(zhuǎn)有兩種情況:
情況1:系統(tǒng)沒(méi)有關(guān)閉自動(dòng)旋轉(zhuǎn)屏幕功能,
這種情況艰赞,支持旋轉(zhuǎn)的界面跟隨用戶手持設(shè)備旋轉(zhuǎn)方向自動(dòng)旋轉(zhuǎn)佣谐。我們需要在當(dāng)前視圖控制器中添加如下方法:
//1.決定當(dāng)前界面是否開(kāi)啟自動(dòng)轉(zhuǎn)屏,如果返回NO方妖,后面兩個(gè)方法也不會(huì)被調(diào)用狭魂,只是會(huì)支持默認(rèn)的方向
- (BOOL)shouldAutorotate {
? ? ? return YES;
}
//2.返回支持的旋轉(zhuǎn)方向
//iPad設(shè)備上,默認(rèn)返回值UIInterfaceOrientationMaskAllButUpSideDwon
//iPad設(shè)備上党觅,默認(rèn)返回值是UIInterfaceOrientationMaskAll
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
? ? return UIInterfaceOrientationMaskAll;
}
//3.返回進(jìn)入界面默認(rèn)顯示方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
? ? return UIInterfaceOrientationPortrait;
}
情況2:?jiǎn)蝹€(gè)界面強(qiáng)制旋轉(zhuǎn)
在程序界面通過(guò)點(diǎn)擊等方式切換到橫屏(尤其是視頻播放的情況)雌澄,有以下兩種方法:
// 方法1:
- (void)setInterfaceOrientation:(UIDeviceOrientation)orientation {
? ? ? if ([[UIDevice currentDevice]? respondsToSelector:@selector(setOrientation:)]) {
? ? ? ? ? [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:orientation]? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? forKey:@"orientation"];
? ? ? ? }
? ? }
//方法2:
- (void)setInterfaceOrientation:(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;
? ? ? ? ? ? [invocation setArgument:&val atIndex:2];
? ? ? ? ? ? [invocation invoke];
? ? ? ? }
? ? }
注意:使用這兩個(gè)方法的時(shí)候,也要確保shouldAutorotate方法返回YES杯瞻,這樣這兩個(gè)方法才會(huì)生效镐牺。還要注意兩者使用的參數(shù)類型不同。
三魁莉、屏幕旋轉(zhuǎn)控制的優(yōu)先級(jí)
事實(shí)上睬涧,如果我們只用上面的方法來(lái)控制旋轉(zhuǎn)的開(kāi)啟與關(guān)閉募胃,并不能符合我們的需求,而且方法無(wú)效畦浓。這是因?yàn)槲覀兒雎粤诵D(zhuǎn)權(quán)限優(yōu)先級(jí)的問(wèn)題痹束。關(guān)于屏幕旋轉(zhuǎn)的設(shè)置有很多,有Xcode的General設(shè)置宅粥,也有info.plist設(shè)置参袱,更還有代碼設(shè)置等电谣,這么多的設(shè)置很是繁雜秽梅。但是這些其實(shí)都是在不同級(jí)別上實(shí)現(xiàn)旋轉(zhuǎn)的設(shè)置,我們會(huì)遇到設(shè)置關(guān)閉旋轉(zhuǎn)無(wú)效的情況剿牺,這就很可能是被上一級(jí)別控制的原因企垦。
我們首先有個(gè)大致的了解,控制屏幕旋轉(zhuǎn)優(yōu)先級(jí)為:工程Target屬性配置(全局權(quán)限) = Appdelegate&&Window > 根視圖控制器> 普通視圖控制器
四晒来、開(kāi)啟屏幕旋轉(zhuǎn)的全局權(quán)限
這里我使用全局權(quán)限來(lái)描述這個(gè)問(wèn)題可能不太準(zhǔn)備钞诡,其實(shí)是設(shè)置我們的設(shè)備能夠支持的方向有哪些,這也是實(shí)現(xiàn)旋轉(zhuǎn)的前提湃崩。
開(kāi)啟屏幕旋轉(zhuǎn)的全局權(quán)限有三種方法荧降,包括通過(guò)Xcode直接配置的兩種方法和代碼控制的一種方法。這三種方法作用相同攒读,但是由于代碼的控制在程序啟動(dòng)之后朵诫,所以也是最有效的。下面分別對(duì)三種方法的用法介紹:
1.Device Orientation屬性配置
我們創(chuàng)建了新工程薄扁,Xcode就默認(rèn)替我們選擇了支持旋轉(zhuǎn)的幾個(gè)方向剪返,這就是Device Orientation屬性的默認(rèn)配置。在Xcode中依次打開(kāi):【General】—>【Deployment Info】—>【Device Orientation】,我們可以看到默認(rèn)支持的設(shè)備方向如下:
可以發(fā)現(xiàn)邓梅,UpsideDown沒(méi)有被默認(rèn)支持脱盲,因?yàn)閷?duì)于iPhone即使勾選也沒(méi)有UpSideDown的旋轉(zhuǎn)效果。我們可以在這里勾選或者取消以修改支持的旋轉(zhuǎn)方向日缨。如果是iPad設(shè)備勾選之后會(huì)同時(shí)支持四個(gè)方向钱反。
值得注意的是,對(duì)于iPhone匣距,如果四個(gè)屬性我們都選或者都不選诈铛,效果和默認(rèn)的情況一樣。
2.Info.Plist設(shè)置
其實(shí)我們?cè)O(shè)置了Device Orientation之后墨礁,再到info.plist中查看Supported interface orientation,我們會(huì)看到:
沒(méi)錯(cuò)幢竹,此時(shí)Supported interface orientation里的設(shè)置和UIDevice Orientation的值一致的,并且我們?cè)谶@里增加或者刪除其中的值恩静,UIDevice Orientation的值也會(huì)隨之變化焕毫,兩者屬于同一種設(shè)置蹲坷。
3.Appdelegate&&Window中設(shè)置
正常情況下,我們的App從Appdelegate中啟動(dòng)邑飒,而Appdelegate所持有唯一的Window對(duì)象是全局的循签,所以在Appdelegate文件中設(shè)置屏幕旋轉(zhuǎn)也是全局有效的。下面的代碼設(shè)置了只支持豎屏和右旋轉(zhuǎn):
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
? ? return? UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
}
值得注意的是:如果我們實(shí)現(xiàn)了Appdelegate的這一方法疙咸,那么我們的App的全局旋轉(zhuǎn)設(shè)置將以這里的為準(zhǔn)县匠,即使前兩種方法的設(shè)置與這里的不同。
五撒轮、開(kāi)啟屏幕旋轉(zhuǎn)的局部權(quán)限(視圖控制器)
在設(shè)置了全局所支持的旋轉(zhuǎn)方向后乞旦,接著就開(kāi)始設(shè)置具體的控制器界面了。我們?cè)谏厦嬉呀?jīng)說(shuō)明了關(guān)于旋轉(zhuǎn)的優(yōu)先級(jí)了题山。而這里主要涉及了三種視圖控制器(UITabbarViewController兰粉,UINavigationBarController ,UIViewController)
自全局權(quán)限開(kāi)啟之后,接下來(lái)具有最高權(quán)限的就是Window的根視圖控制器rootViewController了顶瞳。如果我們要具體控制單個(gè)界面UIViewController的旋轉(zhuǎn)就必須先看一下根視圖控制器的配置情況了玖姑。
當(dāng)然,在一般情況下慨菱,我們的項(xiàng)目都是用UITabbarViewController作為Window的根視圖控制器焰络,然后管理著若干個(gè)導(dǎo)航控制器UINavigationBarController,再由導(dǎo)航欄控制器去管理普通的視圖控制器UIViewController符喝。若以此為例的話闪彼,關(guān)于旋轉(zhuǎn)的優(yōu)先級(jí)從高到低就是UITabbarViewController>UINavigationBarController >UIViewController了。如果具有高優(yōu)先級(jí)的控制器關(guān)閉了旋轉(zhuǎn)設(shè)置洲劣,那么低優(yōu)先級(jí)的控制器是無(wú)法做到旋轉(zhuǎn)的备蚓。
比如說(shuō)我們?cè)O(shè)置要單個(gè)視圖控制器可以自動(dòng)旋轉(zhuǎn),這需要在視圖控制器中增加shouldAutorotate方法返回YES或者NO來(lái)控制囱稽。但如果存在上層根視圖控制器郊尝,而我們只在這個(gè)視圖控制器中實(shí)現(xiàn)方法,會(huì)發(fā)現(xiàn)這個(gè)方法是不走的战惊,因?yàn)檫@個(gè)方法被上層根視圖控制器攔截了流昏。理解這個(gè)原理后,我們有兩種方法實(shí)現(xiàn)自動(dòng)可控的旋轉(zhuǎn)設(shè)置吞获。
方法1:逐級(jí)設(shè)置各視圖控制器况凉,高優(yōu)先級(jí)的視圖控制器影響低優(yōu)先級(jí)控制器,
解決上述的問(wèn)題我們需要設(shè)置UITabbarViewController如下:
//是否自動(dòng)旋轉(zhuǎn)
-(BOOL)shouldAutorotate{
? ? return self.selectedViewController.shouldAutorotate;
}
//支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
? ? return [self.selectedViewController supportedInterfaceOrientations];
}
//默認(rèn)方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
? ? return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
設(shè)置導(dǎo)航控制器UINavigationController如下:
//是否自動(dòng)旋轉(zhuǎn)
//返回導(dǎo)航控制器的頂層視圖控制器的自動(dòng)旋轉(zhuǎn)屬性各拷,因?yàn)閷?dǎo)航控制器是以棧的原因疊加VC的
//topViewController是其最頂層的視圖控制器刁绒,
-(BOOL)shouldAutorotate{
? ? return self.topViewController.shouldAutorotate;
}
//支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
? ? return [self.topViewController supportedInterfaceOrientations];
}
//默認(rèn)方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
? ? return [self.topViewController preferredInterfaceOrientationForPresentation];
}
到這里,我們就應(yīng)該明白了烤黍,其實(shí)就是高優(yōu)先級(jí)的視圖控制器要跟隨低優(yōu)先級(jí)控制器的旋轉(zhuǎn)配置知市。這樣就能夠達(dá)到目的傻盟。
方法2: 另辟蹊徑,使用模態(tài)視圖
使用模態(tài)視圖可以不受這種根視圖控制器優(yōu)先級(jí)的限制嫂丙。這個(gè)也很容易理解娘赴,模態(tài)彈出的視圖控制器是隔離出來(lái)的,不受根視圖控制的影響跟啤。具體的設(shè)置和普通視圖器代碼相同诽表,這里就不累述了。
六隅肥、實(shí)現(xiàn)需求:項(xiàng)目主要界面豎屏竿奏,部分界面橫屏
這其實(shí)也是一個(gè)我們做屏幕旋轉(zhuǎn)最常見(jiàn)的需求,在根據(jù)上面的講述之后武福,我們實(shí)現(xiàn)這個(gè)需求會(huì)很容易议双,但是具體的實(shí)現(xiàn)卻有著不同的思路痘番,我在這里總結(jié)了兩種方法:
方法1:使用基類控制器逐級(jí)控制
步驟:
1.開(kāi)啟全局權(quán)限設(shè)置項(xiàng)目支持的旋轉(zhuǎn)方向
2.根據(jù)第五節(jié)中的方法1,自定義標(biāo)簽控制器和導(dǎo)航控制器來(lái)設(shè)置屏幕的自動(dòng)旋轉(zhuǎn)捉片。
3.自定義基類控制器設(shè)置不支持自動(dòng)轉(zhuǎn)屏,并默認(rèn)只支持豎屏
4.對(duì)項(xiàng)目中需要轉(zhuǎn)屏幕的控制器開(kāi)啟自動(dòng)轉(zhuǎn)屏汞舱、設(shè)置支持的旋轉(zhuǎn)方向并設(shè)置默認(rèn)方向
demo1鏈接: https://github.com/DreamcoffeeZS/Demo_TestRotatesOne.git
方法2:Appdelegate增設(shè)旋轉(zhuǎn)屬性
步驟:
1.在Applegate文件中增加一個(gè)用于記錄當(dāng)前屏幕是否橫屏的屬性
2.需要橫屏的界面伍纫,進(jìn)入界面后強(qiáng)制橫屏,離開(kāi)界面時(shí)恢復(fù)豎屏
demo2鏈接: https://github.com/DreamcoffeeZS/Demo_TestRotatesTwo.git
七昂芜、默認(rèn)橫屏無(wú)效的問(wèn)題
在上面的項(xiàng)目中莹规,我們可能會(huì)遇到一個(gè)關(guān)于默認(rèn)橫屏的問(wèn)題,把它拿出來(lái)細(xì)說(shuō)一下泌神。
我們項(xiàng)目中有支持豎屏的界面A良漱,也有支持橫豎屏的界面B,而且界面B需要進(jìn)入時(shí)就顯示橫屏欢际。從界面A到界面B中母市,如果我們使用第五節(jié)中的方法1會(huì)遇到無(wú)法顯示默認(rèn)橫屏的情況,因?yàn)闆](méi)有旋轉(zhuǎn)設(shè)備损趋,shouldAutorotate就沒(méi)被調(diào)用患久,也就沒(méi)法顯示我們需要的橫屏。這里有兩個(gè)解決方法:
方法1:在自定義導(dǎo)航控制器中增加以下方法
#pragma mark -UINavigationControllerDelegate
//不要忘記設(shè)置delegate
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
? ? [self presentViewController:[UIViewController new] animated:NO completion:^{
? ? ? ? [self dismissViewControllerAnimated:NO completion:nil];
? ? }];
}
這個(gè)方法的缺點(diǎn)是浑槽,原理上利用彈出模態(tài)視圖來(lái)調(diào)用轉(zhuǎn)屏蒋失,造成切換界面的時(shí)候有閃爍效果,體驗(yàn)不佳桐玻。所以這里也只是提供一種思路篙挽,不推薦使用。
方法2:在需要默認(rèn)橫屏的界面里設(shè)置镊靴,進(jìn)入時(shí)強(qiáng)制橫屏铣卡,離開(kāi)時(shí)強(qiáng)制豎屏
關(guān)于這種使用观腊,這個(gè)具體可以參考第五節(jié)中的demo2
注:兩種方法不可同時(shí)使用
八、關(guān)于旋轉(zhuǎn)后的適配問(wèn)題
屏幕旋轉(zhuǎn)的實(shí)現(xiàn)會(huì)帶來(lái)相應(yīng)的UI適配問(wèn)題算行,我們需要針對(duì)不同方向下的界面重新調(diào)整視圖布局梧油。首先我們要能夠監(jiān)測(cè)到屏幕旋轉(zhuǎn)事件,這里分為兩種情況:
1.視圖控制器UIViewController里的監(jiān)測(cè)
當(dāng)發(fā)生轉(zhuǎn)屏事件的時(shí)候州邢,下面的UIViewControoller方法會(huì)監(jiān)測(cè)到視圖View的大小變化儡陨,從而幫助我們適配
/*
This method is called when the view controller's view's size is
changed by its parent (i.e. for the root view controller when its window rotates or is resized).
If you override this method, you should either call super to
propagate the change to children or manually forward the
change to children.
*/
- (void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator NS_AVAILABLE_IOS(8_0);
從注釋里可以看出此方法在屏幕旋轉(zhuǎn)的時(shí)候被調(diào)用,我們使用時(shí)候也應(yīng)該首先調(diào)用super方法量淌,具體代碼使用示例如下:
//屏幕旋轉(zhuǎn)之后骗村,屏幕的寬高互換,我們借此判斷重新布局
//橫屏:size.width > size.height
//豎屏: size.width < size.height
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{
? ? [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
? ? if (size.width > size.height) {
? ? ? ? //橫屏設(shè)置呀枢,為防止遮擋鍵盤,調(diào)整輸入視圖的高度
? ? ? ? self.textView_height.constant = 50;
? ? }else{
? ? ? ? //豎屏設(shè)置
? ? ? ? self.textView_height.constant = 200;
? ? }
}
2.子視圖橫豎屏監(jiān)測(cè)
如果是類似于表視圖的單元格胚股,要監(jiān)測(cè)到屏幕變化實(shí)現(xiàn)適配,我們需要用到layoutSubviews方法裙秋,因?yàn)槠聊磺袚Q橫豎屏?xí)r會(huì)觸發(fā)此方法琅拌,然后我們根據(jù)狀態(tài)欄的位置就可以判斷橫豎屏了,代碼示例如下:
- (void)layoutSubviews {
? ? [super layoutSubviews];
? ? //通過(guò)狀態(tài)欄電池圖標(biāo)判斷橫豎屏
? ? if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationMaskPortrait) {
? ? ? ? //豎屏布局
? ? } else {
? ? ? ? //橫屏布局
? ? }
}
九摘刑、APP啟動(dòng)即全屏
有時(shí)項(xiàng)目需要從App啟動(dòng)就默認(rèn)是橫屏进宝,這里有個(gè)很方便的方法,就是我們?cè)贒evice Orientation屬性配置里設(shè)置如下:
但是只這樣處理的話枷恕,會(huì)讓項(xiàng)目只支持橫屏党晋,所以我們可以在Appdelegate里再次調(diào)整我們所支持的方向,方法已經(jīng)說(shuō)過(guò)徐块,這里就不累述了未玻。
---------------------