mirror of
https://github.com/yattee/yattee.git
synced 2024-11-14 10:08:23 +00:00
97 lines
3.1 KiB
Swift
97 lines
3.1 KiB
Swift
import CoreMotion
|
|
import UIKit
|
|
|
|
public class OrientationTracker {
|
|
public static let shared = OrientationTracker()
|
|
|
|
public static let deviceOrientationChangedNotification = NSNotification.Name("DeviceOrientationChangedNotification")
|
|
|
|
public var currentDeviceOrientation: UIDeviceOrientation = .portrait
|
|
|
|
public var currentInterfaceOrientation: UIInterfaceOrientation {
|
|
switch currentDeviceOrientation {
|
|
case .landscapeLeft:
|
|
return .landscapeLeft
|
|
case .landscapeRight:
|
|
return .landscapeRight
|
|
default:
|
|
return .portrait
|
|
}
|
|
}
|
|
|
|
public var currentInterfaceOrientationMask: UIInterfaceOrientationMask {
|
|
switch currentInterfaceOrientation {
|
|
case .landscapeLeft:
|
|
return .landscapeLeft
|
|
case .landscapeRight:
|
|
return .landscapeRight
|
|
default:
|
|
return .portrait
|
|
}
|
|
}
|
|
|
|
public var affineTransform: CGAffineTransform {
|
|
var angleRadians: Double
|
|
switch currentDeviceOrientation {
|
|
case .portrait:
|
|
angleRadians = 0
|
|
case .landscapeLeft:
|
|
angleRadians = -0.5 * .pi
|
|
case .landscapeRight:
|
|
angleRadians = 0.5 * .pi
|
|
case .portraitUpsideDown:
|
|
angleRadians = .pi
|
|
default:
|
|
return .identity
|
|
}
|
|
return CGAffineTransform(rotationAngle: angleRadians)
|
|
}
|
|
|
|
private let motionManager: CMMotionManager
|
|
private let queue: OperationQueue
|
|
|
|
private init() {
|
|
motionManager = CMMotionManager()
|
|
motionManager.accelerometerUpdateInterval = 0.1
|
|
queue = OperationQueue()
|
|
}
|
|
|
|
public func startDeviceOrientationTracking() {
|
|
motionManager.startAccelerometerUpdates(to: queue) { accelerometerData, error in
|
|
guard error == nil else { return }
|
|
guard let accelerometerData else { return }
|
|
|
|
let newDeviceOrientation = self.deviceOrientation(forAccelerometerData: accelerometerData)
|
|
guard newDeviceOrientation != self.currentDeviceOrientation else { return }
|
|
self.currentDeviceOrientation = newDeviceOrientation
|
|
|
|
NotificationCenter.default.post(name: Self.deviceOrientationChangedNotification,
|
|
object: nil,
|
|
userInfo: nil)
|
|
}
|
|
}
|
|
|
|
public func stopDeviceOrientationTracking() {
|
|
motionManager.stopAccelerometerUpdates()
|
|
}
|
|
|
|
private func deviceOrientation(forAccelerometerData accelerometerData: CMAccelerometerData) -> UIDeviceOrientation {
|
|
let threshold = 0.55
|
|
if accelerometerData.acceleration.x >= threshold {
|
|
return .landscapeLeft
|
|
}
|
|
if accelerometerData.acceleration.x <= -threshold {
|
|
return .landscapeRight
|
|
}
|
|
if accelerometerData.acceleration.y <= -threshold {
|
|
return .portrait
|
|
}
|
|
|
|
if UIDevice.current.userInterfaceIdiom == .pad && accelerometerData.acceleration.y >= threshold {
|
|
return .portraitUpsideDown
|
|
}
|
|
|
|
return currentDeviceOrientation
|
|
}
|
|
}
|