Skip to content

Root view does not fully move down when switching from a taller keyboard to a shorter keyboard #2180

Description

@MargoFG

Description

When IQKeyboardManager is enabled, switching from a taller keyboard to a shorter keyboard while the keyboard remains visible does not correctly restore the root view controller's vertical position.

For example, switching from the Chinese Pinyin 9-key keyboard to the shorter English keyboard reduces the keyboard height, but the root view remains close to the offset used by the taller keyboard.

As a result, an unnecessary blank area remains between the input view and the keyboard, and the entire page stays shifted upward.

Environment

  • IQKeyboardManagerSwift: 8.0.3
  • iOS: 18.x
  • Device: iPhone
  • Integration: CocoaPods
IQKeyboardManager.shared.isEnabled = true

Steps to Reproduce

  1. Enable IQKeyboardManager.
  2. Open a screen containing a text input near the bottom.
  3. Focus the text input.
  4. Switch to the Chinese Pinyin 9-key keyboard.
  5. While the keyboard remains visible, switch to the shorter English keyboard.
  6. Observe the root view controller's vertical position.

Expected Behavior

When the keyboard height decreases, the root view controller should move downward by the corresponding keyboard height difference.

For example, if the keyboard height changes from 374 points to 335 points, the root view should move downward by approximately 39 points.

The input view should remain correctly attached to the top of the current keyboard without leaving an extra blank area.

Actual Behavior

The keyboard frame notification correctly reports the new, shorter keyboard height, but the root view is restored by only a few points.

In the following example:

  • The original keyboard height is 374.
  • The new keyboard height is 335.
  • The expected downward restoration is approximately 39.
  • The calculated moveUp value is only -5.

The root view therefore remains near the position used for the taller keyboard.

Debug Logs

Initial taller keyboard

[IQKeyboard][frame] oldHeight: 0.0 newHeight: 374.0
oldFrame: (0.0, 852.0, 393.0, 0.0)
newFrame: (0.0, 478.0, 393.0, 374.0)

[IQKeyboard][beforeScroll]
keyboardHeight: 374.0
rootOrigin: (0.0, 0.0)
rootBeginOrigin: (0.0, 0.0)
inputRectInWindow: (64.0, 744.0, 223.0, 40.0)
moveUp: 384.0

[IQKeyboard][adjustRoot]
moveUp: 384.0
currentOrigin: (0.0, 0.0)
beginOrigin: (0.0, 0.0)
keyboardHeight: 374.0

After this adjustment, the root view origin becomes approximately:

y = -374

Switching to the shorter keyboard

[IQKeyboard][frame] oldHeight: 374.0 newHeight: 335.0
oldFrame: (0.0, 478.0, 393.0, 374.0)
newFrame: (0.0, 517.0, 393.0, 335.0)

[IQKeyboard][beforeScroll]
keyboardHeight: 335.0
rootOrigin: (0.0, -374.0)
rootBeginOrigin: (0.0, 0.0)
inputRectInWindow: (64.0, 428.0, 223.0, 40.0)
moveUp: -5.0

[IQKeyboard][adjustRoot]
moveUp: -5.0
currentOrigin: (0.0, -374.0)
beginOrigin: (0.0, 0.0)
keyboardHeight: 335.0

The root view moves downward by only 5 points and remains at approximately:

y = -369

The expected root view origin is approximately:

y = -335

Suspected Cause

When the keyboard remains visible and its height decreases, the negative moveUp value appears to be calculated mainly from the current text input position.

However, the root view has already been shifted upward using the previous, taller keyboard height.

The current calculation does not appear to include the difference between the previous keyboard height and the new keyboard height. Consequently, the root view is not fully restored when changing from a taller keyboard to a shorter one.

This appears to happen around the root-controller adjustment logic in:

IQKeyboardManager+Position.swift

Specifically, the negative moveUp branch restores only the newly calculated value instead of also accounting for the keyboard height reduction.

Suggested Solution

When:

  • the keyboard was already visible,
  • the new keyboard is shorter than the previous keyboard, and
  • the root view is currently shifted upward,

the downward restoration distance should be at least the difference between the previous and current keyboard heights.

Conceptually:

let keyboardHeightReduction = max(
    0,
    previousKeyboardHeight - currentKeyboardHeight
)

let downwardDistance = max(
    abs(moveUp),
    keyboardHeightReduction
)

let adjustedMoveUp = -downwardDistance

The adjusted value can then be used by the existing negative moveUp branch.

With the example above:

previousKeyboardHeight = 374
currentKeyboardHeight = 335
keyboardHeightReduction = 39
moveUp = -5
adjustedMoveUp = -39

This restores the root view from approximately -374 to -335, matching the shorter keyboard height.

Additional Notes

  • Keyboard frame notifications are received correctly.
  • The issue occurs while the keyboard remains visible.
  • Switching from a shorter keyboard to a taller keyboard works as expected.
  • The issue is most visible when switching from Chinese Pinyin 9-key to the English keyboard.
  • The same behavior may occur with other keyboard or input-view transitions where the new input view is shorter than the previous one.
  • This issue is independent of the IQKeyboardToolbarManager toolbar.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions