以编程方式锁定 iDevice 方向
Programmatically lock iDevice orientation
在我们正在开发的应用程序中,我们有一个选项让用户选择首选方向 (即,如果他们选择 Portrait
,应用程序将被锁定为纵向,Landscape
并且如果选择 Both
应用程序将在所有方向上运行) 我正在分享我尝试过的代码,我不确定这个功能是否 完全可行。
//MARK:- ORIENTATION
func changeOrientation(orientation: String) {
switch orientation {
case "Portrait":
UserDefaults.standard.set("Portrait", forKey: UserDefaultsKeys.preferredOrientation)
appDelegate.preferredOrientation = "Portrait"
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
break
case "Landscape":
UserDefaults.standard.set("Landscape", forKey: UserDefaultsKeys.preferredOrientation)
appDelegate.preferredOrientation = "Landscape"
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
break
default:
UserDefaults.standard.set("Both", forKey: UserDefaultsKeys.preferredOrientation)
appDelegate.preferredOrientation = "Both"
break
}
/*not necessary*/
let vc = UIViewController()
UIViewController.attemptRotationToDeviceOrientation()//forces to rotate
/*not necessary*/
self.present(vc, animated: false, completion: nil)
UIView.animate(withDuration: 0.3, animations: {
vc.dismiss(animated: false, completion: nil)
})
/*not necessary*/
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask{
get {
switch appDelegate.preferredOrientation {
case "Portrait":
return .portrait
case "Landscape":
return .landscape
default:
return .all
}
}
}
open override var shouldAutorotate: Bool {
get {
return true
}
}
但是如果我在纵向模式下选择 'Landscape',它会自动切换到横向。但是,如果我将设备旋转回纵向,它也能正常工作(这不应该按照要求工作)。该要求类似于我们仅使用纵向模式设置项目时发生的情况,以及当设备旋转到横向模式时它的行为方式。
我刚刚写了一个示例项目来测试这是否可行。好吧,我想是的!不幸的是
UIViewController.attemptRotationToDeviceOrientation()
并没有像我希望的那样神奇地完成工作 - 它比那更复杂一点。
请看下面的代码。您需要的所有魔法都在行动中发生 forceChangeOrientations
.
class ViewController: UIViewController {
enum Orientation {
case Landscape
case Portrait
mutating func changeOrientation() {
if self == .Portrait {
self = .Landscape
}
else {
self = .Portrait
}
}
func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
switch self {
case .Landscape:
return .Landscape
case .Portrait:
return .Portrait
}
}
func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
switch self {
case .Landscape:
return UIInterfaceOrientation.LandscapeLeft
case .Portrait:
return .Portrait
}
}
}
var currentOrientation: Orientation = .Portrait
// Returns a Boolean value indicating whether the view controller's contents should auto rotate.
override func shouldAutorotate() -> Bool {
return true
}
// Returns all of the interface orientations that the view controller supports.
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return currentOrientation.supportedInterfaceOrientations() //UIInterfaceOrientationMask.All
}
// Returns the interface orientation to use when presenting the view controller.
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.Portrait
}
@IBAction func forceChangeOrientations(sender: AnyObject) {
self.currentOrientation.changeOrientation()
let value = self.currentOrientation.preferredInterfaceOrientationForPresentation().rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
}
在我们正在开发的应用程序中,我们有一个选项让用户选择首选方向 (即,如果他们选择 Portrait
,应用程序将被锁定为纵向,Landscape
并且如果选择 Both
应用程序将在所有方向上运行) 我正在分享我尝试过的代码,我不确定这个功能是否 完全可行。
//MARK:- ORIENTATION
func changeOrientation(orientation: String) {
switch orientation {
case "Portrait":
UserDefaults.standard.set("Portrait", forKey: UserDefaultsKeys.preferredOrientation)
appDelegate.preferredOrientation = "Portrait"
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
break
case "Landscape":
UserDefaults.standard.set("Landscape", forKey: UserDefaultsKeys.preferredOrientation)
appDelegate.preferredOrientation = "Landscape"
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
break
default:
UserDefaults.standard.set("Both", forKey: UserDefaultsKeys.preferredOrientation)
appDelegate.preferredOrientation = "Both"
break
}
/*not necessary*/
let vc = UIViewController()
UIViewController.attemptRotationToDeviceOrientation()//forces to rotate
/*not necessary*/
self.present(vc, animated: false, completion: nil)
UIView.animate(withDuration: 0.3, animations: {
vc.dismiss(animated: false, completion: nil)
})
/*not necessary*/
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask{
get {
switch appDelegate.preferredOrientation {
case "Portrait":
return .portrait
case "Landscape":
return .landscape
default:
return .all
}
}
}
open override var shouldAutorotate: Bool {
get {
return true
}
}
但是如果我在纵向模式下选择 'Landscape',它会自动切换到横向。但是,如果我将设备旋转回纵向,它也能正常工作(这不应该按照要求工作)。该要求类似于我们仅使用纵向模式设置项目时发生的情况,以及当设备旋转到横向模式时它的行为方式。
我刚刚写了一个示例项目来测试这是否可行。好吧,我想是的!不幸的是
UIViewController.attemptRotationToDeviceOrientation()
并没有像我希望的那样神奇地完成工作 - 它比那更复杂一点。
请看下面的代码。您需要的所有魔法都在行动中发生 forceChangeOrientations
.
class ViewController: UIViewController {
enum Orientation {
case Landscape
case Portrait
mutating func changeOrientation() {
if self == .Portrait {
self = .Landscape
}
else {
self = .Portrait
}
}
func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
switch self {
case .Landscape:
return .Landscape
case .Portrait:
return .Portrait
}
}
func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
switch self {
case .Landscape:
return UIInterfaceOrientation.LandscapeLeft
case .Portrait:
return .Portrait
}
}
}
var currentOrientation: Orientation = .Portrait
// Returns a Boolean value indicating whether the view controller's contents should auto rotate.
override func shouldAutorotate() -> Bool {
return true
}
// Returns all of the interface orientations that the view controller supports.
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return currentOrientation.supportedInterfaceOrientations() //UIInterfaceOrientationMask.All
}
// Returns the interface orientation to use when presenting the view controller.
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.Portrait
}
@IBAction func forceChangeOrientations(sender: AnyObject) {
self.currentOrientation.changeOrientation()
let value = self.currentOrientation.preferredInterfaceOrientationForPresentation().rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
}