Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix broken keyboard layout after changing styles #51

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

michaelkirk
Copy link
Collaborator

@michaelkirk michaelkirk commented May 31, 2024

FIXES #50

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.

Note there are a couple things I haven't tested yet:

  • I don't use carplay.
  • I don't have a night theme. - I've verified that this works after navigating across the day->night switch.

I'll eventually add those things to my own app and be able to test them, but it might be some weeks. In the meanwhile, I thought it'd be good to have this PR available in case someone else hits this problem. It took me a while to track it down.

@boldtrn
Copy link
Collaborator

boldtrn commented Jun 3, 2024

Thanks for looking into this. Yeah I think especially dark mode could potentially be an issue here. I agree that we should do some more testing on this. What I don't understand from your video, why is the keyboard suddenly open after the navigation? Because the keyboard was closed before starting the navigation. Is this intended? If yes, this feels quite exotic. (I am not saying, we shouldn't merge this, I'd just like to understand this a bit better)

@michaelkirk
Copy link
Collaborator Author

What I don't understand from your video, why is the keyboard suddenly open after the navigation

The keyboard is not suddenly open after navigation. It remains dismissed (12s-14s) until the user taps into the field (15s).

broken-keyboard-layout.mov.mp4

I don't know the private implementation details of how iOS does keyboard presentation, but here's some debugging info that might be relevant:

Originally the app has just one UIWindow:

image

When the keyboard is first presented a UITextEffectsWindow is added:

image

After the input resigns first responder, the keyboard is dismissed, but the UITextEffectsWindow remains (though one of it's views is removed):

image

So that convinced me that even though the keyboard is not visible when the second MapView is dismissed, some of the keyboards containing views and windows have persisted. With the previous logic, those views were being removed and re-added to their window. It seems plausible for iOS to say "don't touch views in our private windows" unless you want things to break.

So my theory is that, by removing/re-adding the containing keyboard views to their window, we've broken something. But the breakage is not apparent until the keyboard is actually shown.

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.
@michaelkirk michaelkirk force-pushed the mkirk/fix-broken-layout branch from a023cfb to c9d2435 Compare July 26, 2024 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Setting styles can break keyboard/sheet layout (via forceRefreshAppearance)
2 participants