-
-
Notifications
You must be signed in to change notification settings - Fork 86
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
feat: keyboard offset on iOS #727
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
kirillzyusko
added
documentation
Improvements or additions to documentation
🍎 iOS
iOS specific
👆 interactive keyboard
Anything related to interactive keyboard dismissing
🚨 requires API changes 🚨
Changes that requires changes in library API
labels
Dec 12, 2024
|
📊 Package size report
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
…changes before macOS 14 -> macOS 15 update)🤞
… gets removed when old screen gets unmounted after new screen mount (iOS 15 case)
kirillzyusko
force-pushed
the
feat/keyboard-offset-ios
branch
from
January 14, 2025 15:31
f2de5a9
to
cee3449
Compare
2 tasks
kirillzyusko
added a commit
that referenced
this pull request
Jan 21, 2025
## 📜 Description Fixed newly discovered warnings. ## 💡 Motivation and Context In paper example I've seen even more warnings and fixed them as well 🙂 initially these warning were added in #727 Follow up for #766 ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### iOS - fixed 2 warnings in `KeyboardMovementObserver`; ## 🤔 How Has This Been Tested? Tested manually. ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
documentation
Improvements or additions to documentation
👆 interactive keyboard
Anything related to interactive keyboard dismissing
🍎 iOS
iOS specific
🚨 requires API changes 🚨
Changes that requires changes in library API
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📜 Description
Added an ability to specify
offset
for interactive keyboard dismissal on iOS.💡 Motivation and Context
In this PR I'm exposing
KeyboardGestureArea
on iOS and adding two props for that:offset
andtextInputNativeID
.This PR is a re-thinking concept of how we work with
inputAccessoryView
on iOS.To make long text short - default
InputAccessoryView
comes with many restrictions, such as not growingTextInput
, unability to specify position on the screen, weird animations on unmount, complexity with managingSafeArea
insets, etc.We already have
KeyboardStickyView
that don't have all that problems, but if you interactively dismiss a keyboard then interactive dismissal starts from a top border of the keyboard (not the input).Taking a step back and utilising
inputAccessoryView
(moving a view from RN hierarchy directly intoinputAccessoryView
) is possible, but comes with a previous set of challenges.In this PR I decided to think about different concepts between iOS/Android and how to make a solution that will work everywhere identically. And the idea is to create an invisible/non-interactable instance of
inputAccessoryView
, that will simply extend the keyboard area (but keyboard-controller will know about that offset and will automatically exclude it from final keyboard dimensions, so you can use everything as you used before).Schematically all process can be shown on a diagram below:
However new approach comes with its own set of challenges. Mainly they come from the fact how keyboard dismissal works on iOS, and in simple words:
Keyboard.dismiss()
/press enter then whole combination (keyboard + inputAccessoryView) is treated as a single keyboard and entire element gets hidden in a single animation.inputAccessoryView
.From all the description above it's clear, that we want to ignore
inputAccessoryView
animations or exclude its height from the animation (when its animated as a single element).To solve the first problem (when keyboard dismissed as a single element) we need to remove
inputAccessoryView
and only then perform an animation. Otherwise if we use default hooksuseKeyboardAnimation
/useReanimatedKeyboardAnimation
that rely on layout animation, then we will see unsynchronized animation (because for example actual keyboard height is 250 + 50, but in JS we give only value of 250, so we will animate from 250 to 0, though actual animation will be from 300 to 0). To fix that I had to swizzle intoresignFirstResponder
. In this method we see, if we haveInvisibleAccessoryView
, then we postpone a keyboard dismissal and remove currentinputAccessoryView
. In this case we will dismiss a keyboard withoutinputAccessoryView
, so it will work as it works before.The second main challenge was a time when to remove
inputAccessoryView
during interactive keyboard dismissal. The initial idea was to remove it as soon as dismiss gesture begins. However I rejected this idea in d11afd6 mainly because it was causing a lot of issues (such as ghost animation when keyboard is fully dismissed). When we remove that code it removes additional complexity and we removeinputAccessoryView
when we callresignFirstResponder
(happens when keyboard gets dismissed, i. e. first phase passed). In this case it works more predictable.Last but not least - it's wort to note, that the idea with invisible
inputAccessoryView
is not new in iOS community, and some even native projects are utilizing it: https://github.com/iAmrMohamed/AMKeyboardFrameTrackerCloses #250
📢 Changelog
Docs
KeyboardGestureArea
is not Android specific anymore;textInputNativeID
description + show how to use it.JS
iOS
forKeyboardGestureArea
in codegen;textInputNativeID
property forKeyboardGestureArea
;inputAccessoryView
on Fabric facebook/react-native#48339interpolator
optional (will beios
oniOS
andlinear
onAndroid
)TextInput
in interactive iOS keyboard example;iOS
KeyboardGestureArea
on iOS as wellInvisibleInputAccessoryView
class;KeyboardEventsIgnorer
class;KeyboardAreaExtender
class;KeyboardOffsetProvider
class;KeyboardEventsIgnorer
class;UIResponderSwizzle
class;shouldIgnoreKeyboardEvents
event toNotification
;nativeID
extension toUIResponder
(and it's mock for a native project);Android
textInputNativeId
;🤔 How Has This Been Tested?
Tested locally on:
📸 Screenshots (if appropriate):
ScreenRecording_01-15-2025.12-54-13.PM_1.MP4
📝 Checklist