重置偏移量,onTapGesture有效,但是onRotated不起作用,为什么?

时间:2020-02-19 09:13:36

标签: rotation swiftui

无论方向是纵向还是横向,我都希望在屏幕底部包含2个矩形的视图。

代码是一个测试,当directionDidChangeNotification发生时,我发现UIDevice.current.orientation.isPortrait和UIScreen.main.bounds.height经常具有错误的值,为什么?

无论如何,测试代码只是在onRotated()中重置offset = 0。但它不起作用;否则onTapGesture可以正常工作。

Q1:SwiftUI是否使用错误的方法? SceneDelegate.orientationDidChangeNotification-> contentView.onRotated()?

Q2:为什么UIDevice.current.orientation.isPortrait和UIScreen.main.bounds.height通常具有错误的值?

Q3:如何让视图以纵向和横向两种方式漂浮在屏幕底部?

let height: CGFloat = 100

struct TestView: View {
    @State var offset = (UIScreen.main.bounds.height - height) / 2

    var body: some View {
        ZStack {
            Text("+")
            VStack(spacing: 0) {
                Rectangle().fill(Color.blue)
                Rectangle().fill(Color.red)
            }
            .frame(width: 100, height: height)
            .offset(y: offset)
            .onTapGesture {
                self.offset = 0
            }
        }
    }

    func onRotated() {
//        let isPortrait =  UIDevice.current.orientation.isPortrait
        offset = 0//(UIScreen.main.bounds.height - height) / 2
//        print("\(isPortrait), screen height = \(UIScreen.main.bounds.height)")
    }
}

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        let contentView = TestView()
        if let windowScene = scene as? UIWindowScene {
            NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification, object: nil, queue: nil) { notification in
                contentView.onRotated()
            }

            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
    ...
}

1 个答案:

答案 0 :(得分:1)

contentView不是引用,它是一个值,因此您只能在回调内部的.onRotated值的副本上调用contentView

    let contentView = TestView() 
    if let windowScene = scene as? UIWindowScene {
        NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification, object: nil, queue: nil) { notification in
            contentView.onRotated() // local copy!!!
        }

代替在TestView中为通知发布者创建侦听器,以便它可以在内部进行自我更改。

此外,尚不清楚意图,但是SwiftUI可以通过EnvironmentValues.horizontalSizeClassEnvironmentValues.verticalSizeClass跟踪尺寸类别,这些尺寸类别会根据设备方向自动更改,因此可以根据您的视图布局这些环境值甚至没有通知。

See here good example on how to use size classes