AbstractSceneView: pin scrollView bottom to keyboardLayoutGuide#4
Conversation
Default `setupScrollViewConstraints()` previously pinned the scroll
view's bottom edge to `self.bottomAnchor`. When the on-screen keyboard
appeared, the scroll view stayed full-height and the keyboard simply
covered the lower portion of the form — including primary CTAs (e.g.
the "Continue" button on a sign-up / set-password screen). The user had
no way to scroll to reveal the covered content.
Switch the default bottom pin to `keyboardLayoutGuide.topAnchor` (iOS 15+).
The system layout guide tracks the keyboard's frame automatically:
- No keyboard on screen → top anchor coincides with
`safeAreaLayoutGuide.bottomAnchor`, so layout looks identical to a
plain `bottomAnchor` pin in the resting state.
- Keyboard appears → top anchor sits at the keyboard's top edge, the
scroll view shrinks, and the existing `contentLayoutGuide` /
`frameLayoutGuide` machinery in `BaseScrollableStackViewOwner`
handles the reflow so the field that took focus stays visible and
the rest of the form is reachable by scrolling.
No observer boilerplate (no `NotificationCenter.default.addObserver` for
`keyboardWillShow/Hide`), no global swizzling (no `IQKeyboardManager`).
Subclasses that override `setupScrollViewConstraints()` should propagate
the change — see updated DocC example on the override hook.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates AbstractSceneView so its owned scroll view tracks the keyboard by pinning its bottom edge to keyboardLayoutGuide.topAnchor, aiming to keep form content reachable when the on-screen keyboard covers the lower part of the screen.
Changes:
- Changed the default bottom constraint in
setupScrollViewConstraints()frombottomAnchortokeyboardLayoutGuide.topAnchor. - Expanded the DocC for
setupScrollViewConstraints()to explain the keyboard-aware behavior. - Updated the override example so subclasses preserve the new keyboard-aware bottom pin.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. Thanks for integrating Codecov - We've got you covered ☂️ |
Two real issues: 1. `BaseScrollableStackViewOwner` was pinning the content view's bottom to `self.bottomAnchor` (or `safeAreaLayoutGuide.bottomAnchor` for pull-to-refresh), but the scroll view itself now stops at `keyboardLayoutGuide.topAnchor`. On devices with a home indicator, the content view extended ~34pt below the scroll view's resting- state frame, causing an unintended blank scrollable strip. Fixed by also pinning the content view's bottom to `keyboardLayoutGuide.topAnchor`, matching the scroll view. This also removes the now-unnecessary `bottomToSafeArea` branch (the pull-to-refresh distinction never affected the actual layout target — `keyboardLayoutGuide.topAnchor` coincides with `safeAreaLayoutGuide.bottomAnchor` when no keyboard is on screen). 2. The keyboard-avoidance docstring claimed "available everywhere the package targets (iOS 15+)", but the package now declares iOS 26 as its minimum platform. The "iOS 15+" mention was meant as "the API itself doesn't require anything newer," but it misleads consumers about the actual deployment-target floor. Reworded to drop the version note and keep just the architectural pitch (no observer boilerplate, no IQKeyboardManager swizzling). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…rea = false The previous revision pinned both the scroll view and content view to `keyboardLayoutGuide.topAnchor`, which by default sits at `safeAreaLayoutGuide.bottomAnchor` when no keyboard is visible. Effect: every scene became 34pt shorter on home-indicator devices, including scenes with no text input — broader than the PR's stated keyboard- avoidance scope, and a regression for full-bleed layouts. Fix: set `keyboardLayoutGuide.usesBottomSafeArea = false` in `setupAbstractSceneView()`. With that property `false`, the guide's top tracks `self.bottomAnchor` (under the home indicator) when no keyboard is up, and only moves up when a keyboard is actually on screen. The resting layout is now identical to pre-keyboard-avoidance for every scene; only scenes that actually present a keyboard see the shrink. Updated the doc comment to reflect the new behavior. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Pull-to-refresh scenes set `contentInsetAdjustmentBehavior = .always` in `AbstractSceneView.setupAbstractSceneView()`, which auto-adds a ~34pt safe-area bottom inset on home-indicator devices. Combined with the previous revision pinning the content view to `keyboardLayoutGuide.topAnchor` (= `self.bottomAnchor` at rest with `usesBottomSafeArea = false`), the scrollable area became contentSize + 34pt-extra-inset = 34pt blank zone below the content. Fix: restore the per-mode bottom anchor for the content view only: - `PullToRefreshCapable`: content view pins to `safeAreaLayoutGuide.bottomAnchor`. The auto-applied 34pt content inset and the safe-area-bound content end now align (no blank zone), and the refresh spinner still clears the home indicator when pulled. - Otherwise: content view pins to `keyboardLayoutGuide.topAnchor`, same as before. Full-bleed at rest (under the home indicator), shrinks when a keyboard appears. The scroll view itself still pins to `keyboardLayoutGuide.topAnchor` in both modes, so keyboard avoidance works regardless. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Picks up the keyboard-avoidance fix (Sajjon/NanoViewController#4): `AbstractSceneView` now pins its scroll view bottom to `keyboardLayoutGuide.topAnchor`, so password / form scenes (set-encryption-password, restore-from-keystore, etc.) automatically shrink when the keyboard appears and the user can scroll to reach the covered Continue button + checkbox. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Default
setupScrollViewConstraints()previously pinned the scroll view's bottom edge toself.bottomAnchor. When the on-screen keyboard appeared, the scroll view stayed full-height and the keyboard simply covered the lower portion of the form — including primary CTAs (e.g. the "Continue" button on a sign-up / set-password screen). The user had no way to scroll to reveal the covered content.Switch the default bottom pin to
keyboardLayoutGuide.topAnchor, and setkeyboardLayoutGuide.usesBottomSafeArea = falseinsetupAbstractSceneView(). The system layout guide tracks the keyboard's frame automatically:usesBottomSafeArea = false, the guide's top sits atself.bottomAnchor(under the home indicator). Resting layout is therefore identical to the previousself.bottomAnchorpin — non-text-input scenes are unaffected.contentLayoutGuide/frameLayoutGuidemachinery inBaseScrollableStackViewOwnerhandles the reflow so the focused field stays visible and the rest of the form is reachable by scrolling.BaseScrollableStackViewOwner's content-view bottom anchor is split per mode to keep the auto-applied content-inset coherent:PullToRefreshCapablescenes usecontentInsetAdjustmentBehavior = .always, which adds a safe-area bottom inset; the content view pins tosafeAreaLayoutGuide.bottomAnchorso the inset and content-end align (no blank scrollable strip), and the refresh spinner clears the home indicator when pulled.keyboardLayoutGuide.topAnchor(which equalsself.bottomAnchorat rest withusesBottomSafeArea = false).No observer boilerplate (no
NotificationCenter.default.addObserverforkeyboardWillShow/Hide), no global swizzling (noIQKeyboardManager).Subclasses that override
setupScrollViewConstraints()should propagate the change — see updated DocC example on the override hook.