iOS 橫豎屏總結筆記

項目APP中總會遇到某些頁面需要橫屏展示珊燎,其他頁面默認豎屏展示。所以總結了一套自己使用的橫豎屏方法遵湖。

首先我查看UIKit的Api文檔發(fā)現(xiàn)有一個UIViewController的分類UIViewControllerRotation


UIViewControllerRotation.png

里面有幾項是:

// 當前Controller是否支持旋轉延旧,YES -- 可以旋轉 NO -- 不支持旋轉 , 默認是YES(iOS 6.0之后可用)
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0);
//  當前Controller支持的旋轉方向迁沫,默認是UIInterfaceOrientationMaskAll(iOS 6.0之后可用)
- (UIInterfaceOrientationMask)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0);
//  當前Controller默認的方向,使用present方式彈出時可用(iOS 6.0之后可用)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0);

只要在需要旋轉的控制器里面重寫這幾個方法近弟,就能實現(xiàn)當前控制器的橫豎屏旋轉了挺智。

當然,首先TARGETS的配置文件需要設置“Device Orientation”配置支持的設備方向。(某些頁面需要橫屏掐頁面需要豎屏的話迫摔,需要勾選上 “Landscape Left” “Landscape Right”泥从,不過具體需要根據(jù)需求確定)


Deployment.png

似乎事情朝著很好的預期進發(fā),但是事實并非如此......(你會發(fā)現(xiàn)即使重寫了這些方法纱烘,頁面并不會按照你的想法去旋轉)

一番查找祈餐,終于找到了原因:

我們APP一般的形式是window的rootViewController一般是UITabBarController,然后UITabBarController的viewControllers一般是多個導航欄UINavigationController哺壶。(或者window的rootViewController是UINavigationController)等等方式蜒谤。

那么要控制window的旋轉山宾,需要從window的rootViewController開始控制旋轉鳍徽,但是系統(tǒng)的UITabBarController默認的旋轉都是打開的阶祭,而且是所有方向都支持,那么我們只能從繼承自UITabBarController的類開始濒募,一級一級的去處理重寫旋轉方向支持。然后我們需要由控制器決定自己是否需要旋轉齿诉,不影響其他頁面的旋轉培他,所以就要一級一級的告知window當前控制器是否需要旋轉。所以我的做法是這樣的:
繼承自UITabBarController的類俊扳,重寫這幾個系統(tǒng)方法:

// 支持設備自動旋轉猛遍,由selectedViewController決定是否支持旋轉
- (BOOL)shouldAutorotate{
    return [self.selectedViewController shouldAutorotate];
}

// 支持旋轉方向号坡,由selectedViewController決定旋轉方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return [self.selectedViewController supportedInterfaceOrientations];
}

// 當前控制器默認的屏幕方向梯醒,由selectedViewController決定旋轉方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}

然后我們App一般的selectedViewController都是UINavigationController,所以在繼承自UINavigationController的類里面同樣重寫這幾個系統(tǒng)方法:

// 支持設備自動旋轉畜隶,由topViewController決定是否要旋轉
- (BOOL)shouldAutorotate{
    return [self.topViewController shouldAutorotate];
}

// 支持旋轉方向号胚,由topViewController決定旋轉方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return [self.topViewController supportedInterfaceOrientations];
}

// 當前控制器默認的屏幕方向,由topViewController決定旋轉方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}

一般我們控制器都有一個基類(例如BaseViewController)箱亿,所有的控制器都繼承自這個基類(BaseViewController)弃秆,然后在基類中同樣重寫這幾個系統(tǒng)方法:

// 這里讓所有控制器都支持旋轉
- (BOOL)shouldAutorotate{
    return YES;
}
// 這里寫默認app的方向,一般app大多都是只支持豎屏脑豹,所以這里return一個UIInterfaceOrientationMaskPortrait值
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

// 這里寫當前控制器默認的屏幕方向锈至,一般app大多都是只支持豎屏,所以這里return一個UIInterfaceOrientationPortrait值 
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationPortrait;
}

這里要記錄一下

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;

這個方法的用途,這個方法主要用于present方式彈出的視圖器作用们拙,例如A push B push C 阁吝,這樣都是push操作的話,這個方法其實并沒有作用突勇。但是 A push B 然后 B present C,此時重寫C控制器里面的這個方法埂奈,就會體現(xiàn)出作用了定躏,present出來的控制器默認是彈出來是朝著什么方向由這個方法決定芹敌,當然這個方法這個方法要配合supportedInterfaceOrientations方法一起垮抗,這兩個返回值要一致(例如preferredInterfaceOrientationForPresentation返回值是UIInterfaceOrientationLandscapeRight右側,那么supportedInterfaceOrientations返回值也要是UIInterfaceOrientationMaskLandscapeRight或者UIInterfaceOrientationMaskLandscape或者UIInterfaceOrientationMaskAllButUpsideDown)液茎,否則就crash了辞嗡。

接著就是正常的碼代碼。楚里。猎贴。一直碼到某一個控制器需要支持旋轉,此時在這個控制器里面重寫下面的方法达址,這樣這個控制器就可以根據(jù)手機的重力感應而旋轉方向了

// 這里重寫此方法趁耗,決定當前控制器要支持的旋轉方向,返回值因項目而定
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskAllButUpsideDown;
}

但是有些情況下我們的app在跳轉的時候就需要從一個豎屏的控制器VcA push到一個只支持橫屏的控制器VcB满葛,那么只重寫這些東西是無法實現(xiàn)push VcB之后就是橫屏罢屈,只會是豎屏,然后手機橫著放才能轉到橫屏缠捌,此時我們就需要在VcB內(nèi)強制把屏幕旋轉到橫屏,這樣就實現(xiàn)了從豎屏VcA push到一個橫屏的控制器VcB谊却,強制旋轉方法如下:

// 先置為Unknown狀態(tài)哑芹,讓系統(tǒng)不知道當前屏幕狀態(tài)
NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
// 然后將orientation的值置為右側,這樣系統(tǒng)就會更新屏幕方向蹦魔,轉到右側
NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];

同時需要配合重寫supportedInterfaceOrientations方法,才能生效乒躺,否則容易crash低缩。

這樣push過去的VcB就是一個橫屏的頁面,但是如果還有在下一級的push VcC咆繁,此時需要將視圖轉回來玩般,否則下一級頁面會出現(xiàn)雖然給定了豎直方向,但是保留了上一級頁面的方向坏为,此時同樣使用這些代碼:

// 先置為Unknown狀態(tài)匀伏,讓系統(tǒng)不知道當前屏幕狀態(tài)
NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
// 然后將orientation的值置為豎直,這樣系統(tǒng)就會更新屏幕方向够颠,轉到豎直方向
NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];

這一段代碼可以放在VcB的viewWillDisappear或者寫在VcC的viewWillAppear都可以的履磨。

還有另外一種方法,如果你的項目沒有基類剃诅,項目已經(jīng)成型了,去改基類的話如果類比較少的話,還好控制一點如筛,但是如果項目比較大抒抬,讓后要一個一個類的去添加基類,耗時耗力擦剑,那么可以使用AppDelegate來控制旋轉。
在AppDelegate的.h文件中添加一個屬性


AppDelegate.png

在AppDelegate的.m文件里面重寫:

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return self.interfaceOrientationMask;
}

指定初始值豎直方向UIInterfaceOrientationMaskPortrait:


UIInterfaceOrientationMaskPortrait.png

然后在需要旋轉的頁面:


ViewController.png

記得在消失的時候將“旋轉開關”置為初始狀態(tài)UIInterfaceOrientationMaskPortrait爬坑,不然其他頁面將會支持旋轉了盾计,那就不是我們想要的效果了赁遗。

再配合

NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];

就可以隨心所欲的旋轉了。哭尝。剖煌。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市侠姑,隨后出現(xiàn)的幾起案子箩做,更是在濱河造成了極大的恐慌,老刑警劉巖邦邦,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件燃辖,死亡現(xiàn)場離奇詭異,居然都是意外死亡妇智,警方通過查閱死者的電腦和手機氏身,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來航徙,“玉大人陷虎,你說我怎么就攤上這事杠袱∥迅澹” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵菩彬,是天一觀的道長潮梯。 經(jīng)常有香客問我,道長耙旦,這世上最難降的妖魔是什么萝究? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮绕娘,結果婚禮上栽连,老公的妹妹穿的比我還像新娘。我一直安慰自己绢陌,他們只是感情好熔恢,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秤掌,像睡著了一般鹰霍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衅谷,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天获黔,我揣著相機與錄音,去河邊找鬼堵未。 笑死盏触,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的赞辩。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼世落,長吁一口氣:“原來是場噩夢啊……” “哼糟需!你這毒婦竟也來了?” 一聲冷哼從身側響起武花,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤杈帐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后干旁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炮沐,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡大年,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了轻要。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垦缅。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖凡恍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嚼酝,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布钧舌,位于F島的核電站涎跨,受9級特大地震影響,放射性物質發(fā)生泄漏碘赖。R本人自食惡果不足惜外构,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撼班。 院中可真熱鬧垒酬,春花似錦、人聲如沸勘究。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽景描。三九已至,卻和暖如春向族,著一層夾襖步出監(jiān)牢的瞬間棠绘,已是汗流浹背再扭。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工适肠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓逛揩,卻偏偏與公主長得像麸俘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子从媚,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容