前言
很長(zhǎng)時(shí)間沒(méi)有更新簡(jiǎn)書椭符,原因不多說(shuō)(因?yàn)閼校罱容^清閑贪绘,想起來(lái)寫一篇文章來(lái)說(shuō)一下iOS橫豎屏輕松切換的過(guò)程徘键。 有些需求整體的App只支持豎屏练对,但是只需要某一部分頁(yè)面支持橫屏,許多的視頻類的App都要在豎屏的情況下進(jìn)行橫屏播放啊鸭,當(dāng)然還有很多的奇葩需求要橫屏來(lái)進(jìn)行實(shí)現(xiàn)锹淌。
廢話少說(shuō),進(jìn)主題
創(chuàng)建項(xiàng)目赠制,App的方向只需要勾選Portrait就行(其實(shí)可以不用勾赂摆,但是能有幾個(gè)項(xiàng)目中不勾的呢,我們還是勾上吧)钟些。
前面說(shuō)可以不勾選因?yàn)槲覀円贏ppDelegate中烟号,重寫這個(gè)方法, 應(yīng)用程序啟動(dòng)的時(shí)候會(huì)調(diào)用這個(gè)方法來(lái)給App所需要的屏幕方向:
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if([ScreenDirectionManager manager].islandscape) {
return UIInterfaceOrientationMaskLandscape;
}else {
return UIInterfaceOrientationMaskAll;
}
}
其中UIInterfaceOrientationMask是一個(gè)NS_OPTIONS政恍, 我們可以隨意組合汪拥,雖然其中有一些組合好的,但是萬(wàn)一不滿足產(chǎn)品的奇葩需求呢篙耗,對(duì)不對(duì)迫筑,要提前留一手。
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;
意思內(nèi)容不用多解釋宗弯,應(yīng)該都能知道什么意思脯燃。
其中ScreenDirectionManager這個(gè)類控制屏幕是否橫屏,是一個(gè)單例就一個(gè)屬性是否需要橫屏蒙保,比較簡(jiǎn)單辕棚。
@interface ScreenDirectionManager : NSObject
+ (instancetype)manager;
@property (nonatomic, assign, getter=islandscape) BOOL landscape;
@end
如果你的App不包括導(dǎo)航欄(UINaviagtionController)或者(UITabbarController),你只需要重寫UIViewController里面的三個(gè)方法就行邓厕,這三個(gè)方法是:
// 返回bool值逝嚎,決定Controller是否自動(dòng)旋轉(zhuǎn)
-(BOOL)shouldAutorotate
//返回一個(gè)Controller支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
//返回現(xiàn)在正在顯示的用戶界面方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
但是一般的應(yīng)用至少有個(gè)導(dǎo)航欄吧,所以呢你還需要自定義導(dǎo)航欄(UINavigationController)详恼,然后在導(dǎo)航欄里面重寫這三個(gè)方法补君,如果不重寫,就無(wú)法達(dá)到你想要的效果昧互,感覺(jué)就像這個(gè)屏幕方向具有傳遞的性質(zhì)赚哗。但是我感覺(jué)UITabbarController的情況應(yīng)該少數(shù)她紫,我這里不討論這個(gè)情況,下次有空再補(bǔ)上屿储,但是我感覺(jué)原理應(yīng)該是一樣的,有興趣的可以自己試一下渐逃。
導(dǎo)航欄的屏幕方向和旋轉(zhuǎn)性質(zhì)要和導(dǎo)航欄最上層的Controller保持一致够掠,所以自定義導(dǎo)航欄重寫的三個(gè)方法是這樣的:
-(BOOL)shouldAutorotate {
return [[self.viewControllers lastObject] shouldAutorotate];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
在ViewController中,重寫上述的三個(gè)方法茄菊,返回自己想要的方向疯潭,那個(gè)改Controller只能是返回的方向,例如:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate {
return YES;
}
在第二個(gè)頁(yè)面中面殖,也就是跳轉(zhuǎn)的頁(yè)面中竖哩,重寫上述的三個(gè)方法,返回自己想要的方向脊僚,然后在viewWillAppear方法中設(shè)定將單例的屬性方向改變相叁,然后根據(jù)UIDevice的orientation這個(gè)屬性,根據(jù)KVC辽幌,強(qiáng)制設(shè)置方向增淹,如下;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[ScreenDirectionManager manager].landscape = YES;
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
//寫這句話的目的是保證后面的一句話產(chǎn)生作用,具體不明白為什么乌企,但是不加上會(huì)出現(xiàn)bug虑润。有明白的可以告知一下。
[[UIDevice currentDevice] setValue:@(UIDeviceOrientationUnknown) forKey:@"orientation"];
[[UIDevice currentDevice] setValue:@(UIDeviceOrientationLandscapeLeft) forKey:@"orientation"];
}
}
還需要在viewWillDisappear中加酵,將單例的橫豎屏屬性改變回來(lái)拳喻,因?yàn)?strong>supportedInterfaceOrientations這個(gè)方法會(huì)觸發(fā)AppDelegate中的方向支持方法。
結(jié)論
文章描述的不太清楚的猪腕,歡迎留言討論冗澈。Demo