From c9d2435793e367655ee48123891c32bb2f36f4cd Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 31 May 2024 16:34:48 -0700 Subject: [PATCH] Fix broken keyboard layout after changing styles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm assuming the motivation for the previous implementation is from https://developer.apple.com/documentation/uikit/uiappearance : > iOS applies appearance changes when a view enters a window, but it > doesn’t change the appearance of a view that’s already in a window. To > change the appearance of a view that’s currently in a window, remove the > view from the view hierarchy and then put it back. Note that we're removing views from not just our own application windows, but all windows (including the keyboard window). By ignoring the keyboard window, my layout issues go away. Previous steps to reproduce: 1. add a map and an input field to the view hierarchy 2. make input field first responder to present keyboard (thus adds keyboard window to application) 3. present another MapView modally (triggers `applyStyle`, which in turn re-adds every view from every window. 4. dismiss the modal mapview 5. make input field first responder again At this point, the views in my application all seem to be inexplicably offset by the keyboard height. --- CHANGELOG.md | 2 ++ MapboxNavigation/StyleManager.swift | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30772394..5505604b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ #endif ``` * Custom location snapping in the `RouteController` via the delegate +* Fix: Broken layout due to keyboard presentation after changing styles or presenting a second MapView + * Merged in ## 3.0.0 (Jun 15, 2024) * The `speak` method in `RouteVoiceController` can be used without a given `RouteProgress` or the `RouteProgress` can explicitly ignored so that it will not be added to the voice instruction. diff --git a/MapboxNavigation/StyleManager.swift b/MapboxNavigation/StyleManager.swift index 1a681d02..8a3fc627 100644 --- a/MapboxNavigation/StyleManager.swift +++ b/MapboxNavigation/StyleManager.swift @@ -180,7 +180,8 @@ open class StyleManager: NSObject { } func refreshAppearance() { - for window in UIApplication.shared.windows { + // re-adding the keyboard window views can break layout. See https://github.com/maplibre/maplibre-navigation-ios/issues/50 + for window in UIApplication.shared.applicationWindows { for view in window.subviews { view.removeFromSuperview() window.addSubview(view) @@ -233,3 +234,14 @@ extension Solar { } } } + +extension UIApplication { + var applicationWindows: [UIWindow] { + windows.filter { window in + let className = String(describing: type(of: window)) + return !className.contains("UIRemoteKeyboardWindow") && + !className.contains("UITextEffectsWindow") && + !className.contains("UIAlertController") + } + } +}