iOS - 自由控制頁面橫豎屏展示

有些時候我們需要用特定方向展示某些頁面(例如固定橫屏展示)甘邀,而不影響其它頁面琅攘。例如一些 app 固定用橫屏播放視頻。這種情況下坞琴,我們就需要在代碼中控制。

注:所有代碼均使用 Swift 4.0

要點

  1. 涉及的 view controller 屬性:shouldAutorotate, supportedInterfaceOrientations, preferredInterfaceOrientationForPresentation
  2. info.plistDevice Orientation 需要把所有會在 app 里出現(xiàn)的頁面方向選上置济,如下圖:
info.plist 里的 Device Orientation
  1. 當(dāng)使用 container controller (UITabBarController, UINavigationController)包裹 view controller 時,系統(tǒng)通過查詢 container controller 的
    supportedInterfaceOrientationsshouldAutorotate 屬性來決定方向
    • 注意:在 navigation controller push/pop view controller锋八,或在 tab bar controller 里改變 selected view controller時浙于,不應(yīng)該改變 view controller 的頁面方向。因為前后 view controller 頁面方向不同的話挟纱,會出現(xiàn)不連貫的奇怪過場動畫羞酗,更重要的是也不符合 container controller 的使用標(biāo)準(zhǔn)。下面會用例子說明紊服。
  2. 當(dāng) present view controller 時胸竞,系統(tǒng)則通過查詢 presented view controller 的 supportedInterfaceOrientations, shouldAutorotate, preferredInterfaceOrientationForPresentation 三個屬性來決定方向

官方文檔解釋

在看代碼之前,需要先了解這三個屬性的定義卫枝。

  • shouldAutorotate: Bool 類型的屬性,決定能否切換頁面方向校赤。默認(rèn)情況下返回 true, 需要配合著 supportedInterfaceOrientations 使用,看條目 supportedInterfaceOrientations 的解釋筒溃。

  • supportedInterfaceOrientations: bit mask 類型的屬性,Swift 下可以使用 UIInterfaceOrientation enum 值的 Set 表示怜奖。使用情景是當(dāng)系統(tǒng)檢測到設(shè)備方向改變時,會訪問 container controllerpresented view controller 的這個屬性來獲取目前所支持的頁面方向歪玲,當(dāng)返回值包括設(shè)備新的頁面方向時迁央,系統(tǒng)會繼續(xù)訪問 shouldAutorotate 來決定是否旋轉(zhuǎn)頁面读慎;當(dāng)返回值不包括時,系統(tǒng)則不會繼續(xù)訪問 shouldAutorotate夭委。

  • preferredInterfaceOrientationForPresentation: UIInterfaceOrientation enum 類型的屬性,當(dāng)在 full screen 下 present view controller 時株灸,系統(tǒng)訪問此屬性來決定 presented view controller 的頁面方向。這里要注意兩點:

    1. 只有在 modalPresentationStylefull screen 時才適用慌烧,其它 style 下不會被訪問
    2. preferredInterfaceOrientationForPresentation 必須是 supportedInterfaceOrientations 的子集,否則當(dāng) present 此頁面時 app 會強退

單純文字太抽象屹蚊,以下通過代碼來詳細描述各個情況下的設(shè)定厕氨。所有代碼均使用 Swift 4 書寫汹粤,如果是 Objective-C, override 相應(yīng)方法即可。

使用 container controller 的例子

例子使用 tab bar controller -> navigation controller -> view controller 的層級結(jié)構(gòu):

view controller 結(jié)構(gòu)

根據(jù)所在頁面控制是否跟隨設(shè)備方向來改變頁面方向的效果:

在 container controller 里控制頁面方向

實現(xiàn)思路是嘱兼,在所有 container 里實現(xiàn) shouldAutorotatesupportedInterfaceOrientations,返回展示的最上層的 view controller 的設(shè)置。
在 tabbar controller 里:

    override var shouldAutorotate: Bool {
        return selectedViewController?.shouldAutorotate ?? false
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return selectedViewController?.supportedInterfaceOrientations ?? .portrait
    }

在 navigation controller 里:

    override var shouldAutorotate: Bool {
        return topViewController?.shouldAutorotate ?? false
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return topViewController?.supportedInterfaceOrientations ?? .portrait
    }

因此在 view controller 里就可以返回需要的值來決定起頁面方向配置接奈。

注意:不建議在同一個 container controller 里前后 view controller 方向不一致的設(shè)定,否則會出現(xiàn)不對稱的過場動畫序宦。
如下例子是豎屏 push橫屏 pop 后利虫,下次豎屏 push 完后的豎屏 pop 動畫還是會和橫屏 pop 一樣:

依舊是橫屏 pop 的過場動畫

目前我知道的解決辦法是:在可以變換頁面方向的 view controller 里換回豎屏 pop挨厚。

Present 例子

Present view controller 相對來說自由很多糠惫,個人認(rèn)為是因為這種方式無論是相互關(guān)系和 UI 關(guān)聯(lián)性都比較獨立于 container controller钉疫。你可以 present 任意方向的 view controller硼讽,同時 dismiss 時的方向也不會影響下次 present 后的 dismiss 方向牲阁。
一個固定 landscapeLeft present 的例子:

固定 landscapeLeft present

present 需要在 presented view controller 里實現(xiàn)三個屬性:

    override var shouldAutorotate: Bool {
        return false
    }
    
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return .landscapeLeft
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscapeLeft
    }

上文提過,present 的這種使用需要 modalPresentationStylefull screenpreferredInterfaceOrientationForPresentation 必須是 supportedInterfaceOrientations 的子集城菊。

同時這里多實現(xiàn)的 preferredInterfaceOrientationForPresentation 是用于控制 presented view controller 出現(xiàn)時的方向。無論設(shè)備或者 presenting view controller 是什么方向凌唬,presented view controller 的方向都會根據(jù)此屬性來設(shè)置。

總結(jié)

  • view controller 的頁面橫豎屏通過三個屬性控制:shouldAutorotate客税,preferredInterfaceOrientationForPresentation况褪,supportedInterfaceOrientations
  • info.plistDevice Orientation 需要包括 app 里所有可能出現(xiàn)的頁面方向
  • 當(dāng)使用 container controller 時更耻,系統(tǒng)通過調(diào)用 container controller 的 shouldAutorotatesupportedInterfaceOrientations 來決定方向
    • container controller 里的前后 view controllers 的方向建議保持一致
  • 當(dāng) present view controller 時,系統(tǒng)通過調(diào)用presented view controllershouldAutorotate秧均,preferredInterfaceOrientationForPresentation食侮,supportedInterfaceOrientations 來決定方向

歡迎任何意見交流 :)
實例項目請點 這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末目胡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子讶隐,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件效五,死亡現(xiàn)場離奇詭異,居然都是意外死亡畏妖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門戒劫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人迅细,你說我怎么就攤上這事∫鸬洌” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵统阿,是天一觀的道長。 經(jīng)常有香客問我扶平,道長帆离,這世上最難降的妖魔是什么结澄? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮概而,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赎瑰。我一直安慰自己王悍,他們只是感情好餐曼,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著源譬,像睡著了一般集惋。 火紅的嫁衣襯著肌膚如雪踩娘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音雷绢,去河邊找鬼翘紊。 笑死蔽氨,一個胖子當(dāng)著我的面吹牛帆疟,可吹牛的內(nèi)容都是我干的鹉究。 我是一名探鬼主播踪宠,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼柳琢!你這毒婦竟也來了匿级?” 一聲冷哼從身側(cè)響起染厅,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤津函,失蹤者是張志新(化名)和其女友劉穎肖粮,沒想到半個月后尔苦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涩馆,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡允坚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了稠项。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涯雅。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡展运,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拗胜,到底是詐尸還是另有隱情蔗候,我是刑警寧澤埂软,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響所灸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜庆寺,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望懦尝。 院中可真熱鬧知纷,春花似錦陵霉、人聲如沸琅轧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽效床。三九已至睹酌,卻和暖如春剩檀,著一層夾襖步出監(jiān)牢的瞬間憋沿,已是汗流浹背沪猴。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工辐啄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留运嗜,地道東北人壶辜。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓担租,卻偏偏與公主長得像,于是被迫代替她去往敵國和親翩活。 傳聞我的和親對象是個殘疾皇子阱洪,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

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

  • /* UIViewController is a generic controller base class th...
    DanDanC閱讀 1,811評論 0 2
  • iOS中菠镇,使用ViewController進行頁面跳轉(zhuǎn)的方法有很多,之前總是想到哪用到哪利耍,最近在review項目的...
    ac3閱讀 18,346評論 2 60
  • 轉(zhuǎn)載自:https://github.com/Tim9Liu9/TimLiu-iOS 目錄 UI下拉刷新模糊效果A...
    袁俊亮技術(shù)博客閱讀 11,926評論 9 105
  • Harvey沒說什么盔粹,只是皺著眉看著Mike的手程癌,“你不去包扎一下嗎舷嗡?”Mike愣了一會兒,顯然還沒從剛才的事件中...
    一酒貓餅閱讀 475評論 0 1
  • 三毛說:心若沒有棲息的地方进萄,走到哪里都是流浪。 如同此刻的我中鼠, 走在這世界上,擁擠的人海中沿癞, 是沉默的,是孤獨的椎扬,...
    乃見閱讀 197評論 0 1