+1

Cách xử lý khóa xoay màn hình trong iOS

Bài toán đặt ra

Bạn có một ứng dụng có nhiều màn hình, với yêu cầu có màn hình bạn hỗ trợ cả ngang và dọc, nhưng có màn hình bạn chỉ hỗ trợ màn hình ngang hay chỉ hỗ trợ màn hình dọc.

Để làm được như vậy, bạn cần phải set lại giá trị orientation của UIDevice.current

Ví dụ set chiều dọc: (thay portrait trên tương ứng chiều mà bạn hỗ trợ)

UIDevice.current.setValue(UIInterfaceOrientationMask.portrait.rawValue, forKey: "orientation")

Trong đó UIInterfaceOrientationMask có hỗ trợ:

public struct UIInterfaceOrientationMask : OptionSet {

    public init(rawValue: UInt)

    
    public static var portrait: UIInterfaceOrientationMask { get }

    public static var landscapeLeft: UIInterfaceOrientationMask { get }

    public static var landscapeRight: UIInterfaceOrientationMask { get }

    public static var portraitUpsideDown: UIInterfaceOrientationMask { get }

    public static var landscape: UIInterfaceOrientationMask { get }

    public static var all: UIInterfaceOrientationMask { get }

    public static var allButUpsideDown: UIInterfaceOrientationMask { get }
}

Để thay đổi giá trị orientation của UIDevice.current, có 2 cách:

Cách 1: Sử dụng AppDelegate

Trong code demo trên mình có tạo 1 struct AppUtility để xử lý xoay màn hình, bản chất cũng chỉ để thay đổi giá trị orientation của UIDevice.current

import UIKit

struct AppUtility {
    
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
        
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationLock = orientation
        }
    }
    
    /// OPTIONAL Added method to adjust lock and rotate to the desired orientation
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
        
        self.lockOrientation(orientation)
        
        UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
    }
    
}

Mình đang để default trong AppDelegate là hỗ trợ tất cả các chiều: var orientationLock = UIInterfaceOrientationMask.all

Ví dụ ở SecondViewController mình hỗ trợ chỉ chiều dọc, còn ViewController ban đầu mình hỗ trợ tất cả các chiều như mặc định:

import UIKit

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        print("Second ViewController")
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
//        AppUtility.lockOrientation(.portrait)
        // Or to rotate and lock
         AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
        
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Don't forget to reset when view is being removed
        AppUtility.lockOrientation(.all)
    }

    
}

Chi tiết những đoạn code trên bạn lấy code ở nhánh master ở https://github.com/oNguyenVanThieu/iOSOrientation về xem nhé

Cách 2: Sử dụng NaviViewController

Cách này có vẻ code ngắn gọn hơn chút 😄

Trong NaviViewController nhớ có đoạn:

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return topViewController!.supportedInterfaceOrientations
    }

Rồi trong từng ViewController override lại biến supportedInterfaceOrientations theo yêu cầu của bạn. Để hiểu hơn bạn lấy tiếp code ở pull sau, rồi chạy thử để hiểu hơn nhé: https://github.com/oNguyenVanThieu/iOSOrientation/pull/3/files


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí