[英]SwiftUI - Determining Current Device and Orientation
I am trying to detect when the device is on iPad and in Portrait.我试图检测设备何时在 iPad 和纵向上。
Currently I use the UIDevice
API in UIKit and use an environment object to watch changes.目前我在 UIKit 中使用
UIDevice
API 并使用环境 object 来观察变化。 I use the solution found here - Determining Current Device and Orientation .我使用此处找到的解决方案 - Determining Current Device and Orientation 。
However the orientationInfo.orientation
is initially always equal to .portrait
until rotated into portrait and then back to landscape.然而,
orientationInfo.orientation
最初总是等于.portrait
直到旋转成纵向然后再回到横向。
So when doing the following to display the FABView
因此,当执行以下操作以显示
FABView
struct HomeView: View {
@EnvironmentObject var orientationInfo: OrientationInfo
let isPhone = UIDevice.current.userInterfaceIdiom == .phone
var body: some View {
ZStack(alignment: .bottom) {
#if os(iOS)
if isPhone == false && orientationInfo.orientation == .portrait {
FABView()
}
#endif
}
}
}
The view is loaded when the iPad is initially in landscape, but when changing to portrait and back to landscape is then removed.当 iPad 最初处于横向时,将加载视图,但当更改为纵向并返回横向时,将被删除。 Why is this happening and how can I make sure the view isn't loaded on first load?
为什么会发生这种情况,如何确保在第一次加载时未加载视图?
Full Code完整代码
struct HomeTab: View {
var body: some View {
NavigationView {
HomeView()
.environmentObject(OrientationInfo())
}
}
}
struct HomeView: View {
@EnvironmentObject var orientationInfo: OrientationInfo
let isPhone = UIDevice.current.userInterfaceIdiom == .phone
var body: some View {
ZStack(alignment: .bottom) {
#if os(iOS)
if isPhone == false && orientationInfo.orientation == .portrait {
FABView()
}
#endif
}
}
}
final class OrientationInfo: ObservableObject {
enum Orientation {
case portrait
case landscape
}
@Published var orientation: Orientation
private var _observer: NSObjectProtocol?
init() {
// fairly arbitrary starting value for 'flat' orientations
if UIDevice.current.orientation.isLandscape {
self.orientation = .landscape
}
else {
self.orientation = .portrait
}
// unowned self because we unregister before self becomes invalid
_observer = NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification, object: nil, queue: nil) { [unowned self] note in
guard let device = note.object as? UIDevice else {
return
}
if device.orientation.isPortrait {
self.orientation = .portrait
}
else if device.orientation.isLandscape {
self.orientation = .landscape
}
}
}
deinit {
if let observer = _observer {
NotificationCenter.default.removeObserver(observer)
}
}
}
You can use UIDevice.orientationDidChangeNotification
for detecting orientation changes but you shouldn't rely on it when the app starts.您可以使用
UIDevice.orientationDidChangeNotification
来检测方向更改,但在应用启动时不应依赖它。
UIDevice.current.orientation.isValidInterfaceOrientation
will be false at the beginning and therefore both UIDevice.current.orientation.isValidInterfaceOrientation
将在开始时为假,因此两者
UIDevice.current.orientation.isLandscape
and和
UIDevice.current.orientation.isPortrait
will return false
.将返回
false
。
Instead you can use interfaceOrientation
from the first window scene:相反,您可以使用第一个 window 场景中的
interfaceOrientation
:
struct ContentView: View {
@State private var isPortrait = false
var body: some View {
Text("isPortrait: \(String(isPortrait))")
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
guard let scene = UIApplication.shared.windows.first?.windowScene else { return }
self.isPortrait = scene.interfaceOrientation.isPortrait
}
}
}
Also note that device orientation is not equal to interface orientation .另请注意,设备方向不等于界面方向。 When the device is upside down in portrait mode, device orientation is portrait but interface orientation can be landscape as well.
当设备在纵向模式下倒置时,设备方向为纵向,但界面方向也可以为横向。
I think it's better to rely on the interface orientation in your case.我认为在您的情况下最好依靠界面方向。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.