Как вычислить реальный размер окна в Mac Catalyst в macOS 11

Я портировал игру на macOS с помощью Mac Catalyst. Контент игры не изменяется динамически, поэтому я установил фиксированное соотношение сторон 3: 4 (например, iPad в портретной ориентации) в начале приложения. Я добавил это в свой класс AppDelegate:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        #if targetEnvironment(macCatalyst)
                        /* some margin */
            let titleHeight: CGFloat = 34 * 4
            UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.forEach { windowScene in
                windowScene.titlebar?.titleVisibility = .hidden
                /* screen was always 1920x1080 in macOS Catalina */
                let height = windowScene.screen.nativeBounds.height - titleHeight
                let width = 3 * height / 4
                windowScene.sizeRestrictions?.minimumSize = CGSize(width: width, height: height)
                windowScene.sizeRestrictions?.maximumSize = CGSize(width: width, height: height)
            }
        #endif
    }

Это помогает исправить аспект, но на 15-дюймовом MacBook Pro окно выглядело маленьким. Apple подтвердила, что Каталина всегда сообщала 1920x1080, читайте здесь.

В macOS 11 это было исправлено, поэтому теперь в 15-дюймовом MacBook Pro для настроек дисплея Retina по умолчанию я получаю:

nativeBounds: 3360x2100
bounds: 1680x1050
nativeScale: 2
scale: 2

Однако, если я установлю высоту в sizeRestrictions fixed на 1050, окно будет слишком коротким. Если я установлю 2100, окно будет примерно на 30% выше экрана и за пределами его границ.

Я прочитал в правилах пользовательского интерфейса, Приложения Mac Catalyst уменьшаются на 77%, поэтому высота примерно 1400, похоже, здесь работает. Есть ли способ получить эту шкалу программно?

На данный момент я жестко запрограммировал 1.3 * screen.bounds.height в коде. Я не на 100%, это правильное значение для sizeRestrictions, или, если это просто так на этом экране.


person endavid    schedule 15.11.2020    source источник


Ответы (1)


Я думаю, вам лучше всего взломать свой способ настройки contentAspectRatio NSWindow, которое заблокирует ваш контент до желаемого соотношения сторон. (Существует также свойство NSWindow.contentRatio, которое ограничивает размер окна, но я думаю, что contentAspectRatio - это то, что вам нужно.)

  1. Получите динамическую библиотеку, чтобы упростить следующее.

  2. Получите AppKit NSWindow из текущего UIWindow:

extension UIWindow {
    var nsWindow: NSObject? {
        var nsWindow = Dynamic.NSApplication.sharedApplication.delegate.hostWindowForUIWindow(self)
        if #available(macOS 11, *) {
            nsWindow = nsWindow.attachedWindow
        }
        return nsWindow.asObject
    }
}
  1. Как только window.nsWindow не равно нулю (вам может потребоваться подождать viewDidAppear), установите его contentAspectRatio на 4: 3:
Dynamic(view.window?.nsWindow).contentAspectRatio = CGSize(width: 4, height: 3)
person Adam    schedule 14.12.2020
comment
Я должен упомянуть: Dynamic позволяет легко сделать это в Swift. Если вы используете Objective-C (или не возражаете против перехода на ObjC), то весь приведенный выше код можно довольно легко выполнить с помощью NSClassFromString. - person Adam; 16.12.2020