yattee/iOS/OrientationTracker.swift

99 lines
3.1 KiB
Swift
Raw Normal View History

2022-07-09 22:29:13 +00:00
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 }
2022-09-28 14:27:01 +00:00
guard let accelerometerData else { return }
2022-07-09 22:29:13 +00:00
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
)
2022-07-09 22:29:13 +00:00
}
}
public func stopDeviceOrientationTracking() {
motionManager.stopAccelerometerUpdates()
}
private func deviceOrientation(forAccelerometerData accelerometerData: CMAccelerometerData) -> UIDeviceOrientation {
2022-08-09 19:09:49 +00:00
let threshold = 0.55
if accelerometerData.acceleration.x >= threshold {
2022-07-09 22:29:13 +00:00
return .landscapeLeft
2023-06-17 12:09:51 +00:00
}
if accelerometerData.acceleration.x <= -threshold {
2022-07-09 22:29:13 +00:00
return .landscapeRight
2023-06-17 12:09:51 +00:00
}
if accelerometerData.acceleration.y <= -threshold {
2022-07-09 22:29:13 +00:00
return .portrait
2023-06-17 12:09:51 +00:00
}
2023-11-25 18:26:44 +00:00
if UIDevice.current.userInterfaceIdiom == .pad && accelerometerData.acceleration.y >= threshold {
2022-07-09 22:29:13 +00:00
return .portraitUpsideDown
}
2023-11-25 18:26:44 +00:00
2023-06-17 12:09:51 +00:00
return currentDeviceOrientation
2022-07-09 22:29:13 +00:00
}
}