Сброс смещения, onTapGesture работает, но onRotated не работает, почему? - PullRequest
0 голосов
/ 19 февраля 2020

Я хочу, чтобы представление, содержащее 2 прямоугольника, плавающих в нижней части экрана, независимо от ориентации, книжной или альбомной.

Код - это тест, когда происходит ориентацияDidChangeNotification, я нашел UIDevice.current.orientation.isPortrait и UIScreen.main.bounds.height часто имеют неправильное значение, почему?

В любом случае, тестовый код просто сбрасывается смещение = 0 в onRotated (). но это не работает; в противном случае onTapGesture работает нормально.

В1: Это неверный путь для 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 Ответ

1 голос
/ 19 февраля 2020

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.horizontalSizeClass и EnvironmentValues.verticalSizeClass, которые автоматически изменяются в зависимости от ориентации устройства, поэтому можно сделать макет вашего представления в зависимости от этих значений среды даже без уведомления.

Смотрите здесь хороший пример того, как использовать классы размера

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...