這次又踩了一個(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)方式如下:
-
在 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ò)誤顯示 -
在 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ì)為豎屏, 以及左橫屏和右橫屏.
-
在每個(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
.