如何让iPhone仅在左右倾斜时控制屏幕对象位置?
解决iPhone仅左右倾斜时屏幕对象位置变化的问题
当前代码的问题在于直接使用设备坐标系的重力x分量计算倾斜角度,当设备横屏时,设备的轴与界面的轴不再对应,导致上下倾斜(俯仰)被误判为左右倾斜。以下是修正方案:
核心思路
根据当前界面的横竖屏方向,选择对应的重力分量,确保只响应相对于界面的左右倾斜,忽略上下倾斜的影响。
修改后的代码
1. 修正MotionManager类
import SwiftUI import CoreMotion import UIKit class MotionManager: ObservableObject { private var motion = CMMotionManager() @Published var tiltAngle: Double = 0.0 private var orientationObserver: NSObjectProtocol? init() { startMotionUpdates() observeOrientationChanges() } // 监听设备方向变化 private func observeOrientationChanges() { orientationObserver = NotificationCenter.default.addObserver( forName: UIDevice.orientationDidChangeNotification, object: nil, queue: .main ) { _ in } } private func startMotionUpdates() { guard motion.isDeviceMotionAvailable else { return } motion.deviceMotionUpdateInterval = 1.0 / 60.0 motion.startDeviceMotionUpdates(to: .main) { [weak self] data, error in guard let self = self, let data = data else { return } DispatchQueue.main.async { let gravity = data.gravity let interfaceOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? .portrait // 根据界面方向选择对应的水平倾斜分量 var horizontalTilt: Double switch interfaceOrientation { case .portrait: horizontalTilt = gravity.x case .portraitUpsideDown: horizontalTilt = -gravity.x case .landscapeLeft: horizontalTilt = gravity.y case .landscapeRight: horizontalTilt = -gravity.y default: horizontalTilt = gravity.x } // 转换为角度并限制范围(可选,避免过度旋转) let rollAngle = horizontalTilt * 180 / .pi self.tiltAngle = max(min(rollAngle, 30), -30) } } } deinit { if let observer = orientationObserver { NotificationCenter.default.removeObserver(observer) } motion.stopDeviceMotionUpdates() } }
2. 保持LevelView不变
struct LevelView: View { @StateObject private var motionManager = MotionManager() var body: some View { GeometryReader { geometry in ZStack { VStack(spacing: 0) { Rectangle() .fill(Color.white) .frame(height: geometry.size.height / 2) Rectangle() .fill(Color.orange) .frame(height: geometry.size.height / 2) } .rotationEffect(.degrees(motionManager.tiltAngle), anchor: .center) } } .ignoresSafeArea() } }
关键说明
- 通过监听
UIDevice.orientationDidChangeNotification,确保方向变化时能正确切换重力分量的选择 - 根据界面方向映射重力分量:
- 竖屏时使用
gravity.x(设备左右对应界面左右) - 横屏左时使用
gravity.y(设备上下对应界面左右) - 横屏右时使用
-gravity.y(设备上下反向对应界面左右) - 倒转竖屏时使用
-gravity.x(设备左右反向对应界面左右)
- 竖屏时使用
- 可选的角度范围限制(±30度)避免界面过度旋转,提升用户体验
测试注意事项
- 需在真机上测试,模拟器的重力感应模拟不够精准
- 在项目的
Info.plist中配置支持的界面方向(竖屏、横屏左右等)
内容的提问来源于stack exchange,提问作者Oleh
相关产品推荐
相关产品推荐

