<iOS 實(shí)踐經(jīng)驗(yàn)>設(shè)置 APP 中某些界面可以進(jìn)行旋轉(zhuǎn)的正確姿勢(shì)

這次又踩了一個(gè)坑, 雖然網(wǎng)上有很多解決方案, 但總是照葫蘆畫(huà)瓢, 導(dǎo)致實(shí)現(xiàn)出來(lái)問(wèn)題百出, 后面查到 Programming iOS 11 書(shū)上的 306 頁(yè) Initial orientation 一節(jié), 短短幾句話就概括了正確的辦法. 所以說(shuō), 還是要多看書(shū)啊.

APP 情況描述: 當(dāng)前 APP 總體是標(biāo)準(zhǔn)的豎屏界面, 但在 APP 中有一個(gè)統(tǒng)計(jì)界面是橫屏的, 且橫屏狀態(tài)下需要對(duì)設(shè)備旋轉(zhuǎn)作出響應(yīng), 即可以左橫屏或右橫屏.

正確的實(shí)現(xiàn)方式如下:

  1. 在 APP 的 info.plist 中只設(shè)置允許旋轉(zhuǎn)為 portait, 即設(shè)置只允許豎向顯示.
    這個(gè)設(shè)置非常重要, 因?yàn)槿绻?info.plist 中有其他方向設(shè)置的話, 每次當(dāng) APP 啟動(dòng)后, APP 會(huì)根據(jù)當(dāng)前最接近的旋轉(zhuǎn)方向來(lái)旋轉(zhuǎn)屏幕, 如果主界面設(shè)計(jì)為豎屏的話, 則就會(huì)出現(xiàn)顯示異常.
    下面的圖就是當(dāng)手機(jī)橫向放置的情況下打開(kāi) APP, 主界面設(shè)計(jì)為豎屏?xí)r候的錯(cuò)誤顯示:

    錯(cuò)誤顯示

  2. 在 APP Delegate 中實(shí)現(xiàn)如下方法, 指定允許的旋轉(zhuǎn)方向:

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return [.portrait, .landscapeLeft, .landscapeRight]
    }
    

    其中的旋轉(zhuǎn)方向設(shè)置為在 APP 中可能出現(xiàn)的旋轉(zhuǎn), 這里設(shè)計(jì)為豎屏, 以及左橫屏和右橫屏.

  3. 在每個(gè)獨(dú)立的視圖控制器中設(shè)置它們的旋轉(zhuǎn)方向, 要注意的是, 容器控制器(比如導(dǎo)航控制器)的旋轉(zhuǎn)設(shè)置會(huì)覆蓋子控制器的設(shè)置, 故需要特殊處理.
    APP 中 window 的根控制器正好是一個(gè)導(dǎo)航控制器, 在導(dǎo)航控制器中需要這樣寫(xiě):

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        let topVCRotate = self.topViewController?.supportedInterfaceOrientations
        return topVCRotate ?? .portrait
    }
    
    override var shouldAutorotate: Bool {
        let topVCRotate = self.topViewController?.shouldAutorotate
        return topVCRotate ?? false
    }
    

    而導(dǎo)航控制器的子控制器中, 就直接設(shè)置旋轉(zhuǎn)方向以及是否允許旋轉(zhuǎn)即可.
    這里是橫屏界面的設(shè)置:

    override var shouldAutorotate: Bool {
        return true
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return [.landscapeLeft, .landscapeRight]
    }
    

    這里是豎屏界面的設(shè)置:

    override var shouldAutorotate: Bool {
        return true
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
    

通過(guò)上述設(shè)置, 就解決了在一個(gè) APP 中單獨(dú)某些界面支持不同方向的旋轉(zhuǎn)以及是否允許某些界面可以旋轉(zhuǎn).

上述只是針對(duì)單個(gè)頁(yè)面顯示時(shí)候的解決方法. 但是有一種特殊情況, 比如頁(yè)面 A 設(shè)計(jì)為橫屏, 頁(yè)面 B 設(shè)計(jì)為豎屏, 當(dāng)從頁(yè)面 A 返回到頁(yè)面 B, 此時(shí) B 頁(yè)仍然會(huì)顯示為橫屏. 這樣的情況下, 就需要特殊處理.

新建一個(gè)方法:

    func changeToPreferredOrientation(orientation: UIInterfaceOrientation) {
        let orUnknown = NSNumber(value: UIInterfaceOrientation.unknown.rawValue)
        UIDevice.current.setValue(orUnknown, forKey: "orientation")
        let rotatePreferred = NSNumber(value: orientation.rawValue)
        UIDevice.current.setValue(rotatePreferred, forKey: "orientation")
    }

代碼中的前面兩行是為了繞過(guò)一個(gè)蘋(píng)果坑必須添加的...

viewWillAppear 中調(diào)用它即可. 不過(guò)要注意的是, 這個(gè)方法要能達(dá)到效果, 還有一個(gè)條件, 即將視圖控制器的 shouldAutorotate 屬性重寫(xiě)為返回 true.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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