hooks
hooks copied to clipboard
Add animatedKeyboardHeight in useKeyboard hook
Summary
In order to animate properly based on the keyboard apparition, this PR add a new value in useKeyboard
hook called animatedKeyboardHeight
.
It also add a new hook useAnimatedValue
that just wrap the Animated.Value
into a useRef
hook.
Solve #81
Test Plan
import { useKeyboard } from '@react-native-community/hooks'
const keyboard = useKeyboard()
<Animated.View style={{height: keyboard.animatedKeyboardHeight}} />
Compatibility
OS | Implemented |
---|---|
iOS | ✅ |
Android | ✅ |
Web | ❌ |
Checklist
- [X] I have tested this on a device and a simulator
- [X] I added the documentation in
README.md
- [X] I updated the typed files (TS and Flow)
- [X] I've created a snack to demonstrate the changes: https://snack.expo.io/@magrin_j/usekeyboard-animatedkeyboardheight
This looks great! Would love to see a Snack posted so that I can try it out ☺️
Currently it doesn't seem to handle when the keyboard changes height? 🤔 e.g. when switching between emoji and text input
This looks great! Would love to see a Snack posted so that I can try it out ☺️
Currently it doesn't seem to handle when the keyboard changes height? 🤔 e.g. when switching between emoji and text input
You can find the snack just here: https://snack.expo.io/@magrin_j/usekeyboard-animatedkeyboardheight
It's actually working even if the keyboard height change when switching between classic keyboard and emoji by example. In the snack I've added an extra 150ms duration in the animation because when it's a switch between two kind of keyboard the duration is set to 0, what do you think about that, we should actually put a default duration no ?
It's actually working even if the keyboard height change when switching between classic keyboard and emoji by example. In the snack I've added an extra 150ms duration in the animation because when it's a switch between two kind of keyboard the duration is set to 0, what do you think about that, we should actually put a default duration no ?
Since the keyboard itself isn't animated when we are switching between different layouts, I think that the duration should stay as 0 in those cases.
I think that an important use case that should be addressed by this is having a view that spans the entire screen, but doesn't get covered by the keyboard. The goal here is that the view should always be the exact space visible over the keyboard and thus it's important that the durations are exactly the same as how the keyboard moves.
If we added an extra duration, elements would be partially covered by the keyboard when switching to a higher layout, and then they would animate up from under the keyboard. Since the OS doesn't have an animation when switching layouts, I don't think we should either ☺️
I've modified the Snack slightly here to show what I mean:
https://snack.expo.io/@linusu/usekeyboard-animatedkeyboardheight-linusu
As you can see it is almost perfect, it's just the easing curves that are off a bit (at least on iOS, haven't had time to test Android yet).
Frame 0 | Frame 1 | Frame 2 |
---|---|---|
![]() |
![]() |
![]() |
Frame 8 | Frame 9 | Frame 10 |
---|---|---|
![]() |
![]() |
![]() |
Frame 11 | Frame 12 | Frame 13 |
---|---|---|
![]() |
![]() |
![]() |
Frame 24 | Frame 25 | Frame 26 |
---|---|---|
![]() |
![]() |
![]() |
I know that this might be crazy levels of attention to details 😂 but I would really like to get this within a few pixels of right so that it looks really nice for the app I'm currently working on!
Okay, I have all the points now, I just need to figure out the curve to produce them 😁
Frame | Pixels |
---|---|
0 | 0 |
1 | 93 |
2 | 279 |
3 | 371 |
4 | 456 |
5 | 531 |
6 | 595 |
7 | 649 |
8 | 694 |
9 | 733 |
10 | 761 |
11 | 785 |
12 | 818 |
13 | 830 |
14 | 840 |
15 | 846 |
16 | 852 |
17 | 858 |
18 | 864 |
19 | 866 |
20 | 868 |
21 | 868 |
22 | 870 |
23 | 870 |
24 | 872 |
25 | 872 |
26 | 873 |
It's actually working even if the keyboard height change when switching between classic keyboard and emoji by example. In the snack I've added an extra 150ms duration in the animation because when it's a switch between two kind of keyboard the duration is set to 0, what do you think about that, we should actually put a default duration no ?
Since the keyboard itself isn't animated when we are switching between different layouts, I think that the duration should stay as 0 in those cases.
I think that an important use case that should be addressed by this is having a view that spans the entire screen, but doesn't get covered by the keyboard. The goal here is that the view should always be the exact space visible over the keyboard and thus it's important that the durations are exactly the same as how the keyboard moves.
If we added an extra duration, elements would be partially covered by the keyboard when switching to a higher layout, and then they would animate up from under the keyboard. Since the OS doesn't have an animation when switching layouts, I don't think we should either ☺️
I've modified the Snack slightly here to show what I mean:
https://snack.expo.io/@linusu/usekeyboard-animatedkeyboardheight-linusu
As you can see it is almost perfect, it's just the easing curves that are off a bit (at least on iOS, haven't had time to test Android yet).
I know that this might be crazy levels of attention to details 😂 but I would really like to get this within a few pixels of right so that it looks really nice for the app I'm currently working on!
Ok, you're right, it's better to keep the duration to 0 as it's not animated during the switch 🙂
For the easing curve, I guess we can take a look of what's using natively to produce the animation, like Easing.linear
or something else, changing this could solve the issue, or if not we can create an interpolation array to produce a new output that exactly match the keyboard.
@LinusU Apparently with LayoutAnimation
api we can match the animation, but it's not using Animated.Value
...
https://github.com/facebook/react-native/issues/4812 https://github.com/facebook/react-native/blob/0b9ea60b4fee8cacc36e7160e31b91fc114dbc0d/Libraries/Components/Keyboard/Keyboard.js#L182
The animation curse is defined like that in Native side: https://github.com/facebook/react-native/blob/d0871d0a9a373e1d3ac35da46c85c0d0e793116d/React/Modules/RCTLayoutAnimation.m#L57
Ahh, cool, I've never heard of LayoutAnimation
before, interesting. It seems like it's experimental on Android though 😅
I managed to create a very close beizer curve by simply overlaying a plot of the values I collected and playing with the knobs 😄

But for some reason the duration of the animation simply isn't correct 🤔 I have to add 167ms
in order for the durations to match, and I cannot figure out why 😫
@LinusU Yes, it’s actually still experimental on Android, and it’s not working with Animated.Value from what I’ve understood. The animation is triggered for the next render with LayoutAnimation.
Really strange for the extra duration as without, it actually match time. Not the curve, but the time should be fine 😕
When you’ve done your screenshot and to estimate the frame and height, did you enable the slow animation mode ? If so, the duration will not match as it’s slowed
When you’ve done your screenshot and to estimate the frame and height, did you enable the slow animation mode ? If so, the duration will not match as it’s slowed
Yes I tried running in slow mode, the problem is that the duration is still reported as 250ms
in slow mode so I couldn't match my animation with that one automatically.
I would really like to know the slow down factor as it would help me debugging the delay issue. If I multiply the duration by 20x, the duration seem to match perfectly when running in slow mode without me adding the extra duration. If I multiply by 12x and also add 12x my extra duration, everything also matches up.
When running in normal mode, both in simulator and on device, I need the to add the extra duration in order for the animations to match 😕
When you’ve done your screenshot and to estimate the frame and height, did you enable the slow animation mode ? If so, the duration will not match as it’s slowed
Yes I tried running in slow mode, the problem is that the duration is still reported as
250ms
in slow mode so I couldn't match my animation with that one automatically.I would really like to know the slow down factor as it would help me debugging the delay issue. If I multiply the duration by 20x, the duration seem to match perfectly when running in slow mode without me adding the extra duration. If I multiply by 12x and also add 12x my extra duration, everything also matches up.
When running in normal mode, both in simulator and on device, I need the to add the extra duration in order for the animations to match 😕
Sorry for the delay, I'm little bit busy this week, I'll try to take a look as soon as I can, let me know if you figure it out ! 👍
No worries, I've had a very busy week as well, might get some more time this weekend ☺️
i didnt see any update, plz help @magrinj @LinusU