Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: react on tag changes (#216)
## 📜 Description Improved `KeyboardAwareScrollView` example - now it react on `TextInput` focus changes 🙂 ## 💡 Motivation and Context I highlighted key changes below: ### Interpolation depends on previous keyboard size Before it was a fixed number (0). But since the size of the keyboard can be different per different `TextInput` types - we have to interpolate value from previous keyboard size to the new one. Otherwise the animation when keyboard changes its size looks slightly ugly (will have a jump in beginning). Just as an example let's imagine, that the keyboard is changing size from `200` to `300` and you need to scroll from `100` to `200`. The current scroll position is `100` and you interpolate as before from 0 to 300. In this case, when keyboard size grows from 200 to 300 first scrollTo will scroll to ~160. So 60% of the smooth transition will be missed 😔 If we interpolate from `previousKeyboardSize`, then we will interpolate from `200` to `300` (as expected) and we'll have a smooth transition for all distance. ### Assure `TextInput` is not overlapped by `Keyboard` in `onEnd` handler Sometimes `onMove` handler can be missed. It happens in two cases: - on iOS when TextInput was changed - keyboard transition is instant and `onMove` will not be triggered; - on Android when TextInput was changed and keyboard size wasn't changed. To handle these cases I've decided to run `scrollTo` in `onEnd` handler. For plain transition it will not have any effect, because scroll position already will be as the desired one. However for cases above it'll handle TextInput focus changes and will assure, that the `TextInput` is always above the Keyboard 🙂 ### Back transition To assure smooth back transition I've introduced `scrollBeforeKeyboardMovement` (updated whenever `TextInput` becomes a focus). Later this variable is used in interpolation, when keyboard hides. Also I do a layout substitution in `onEnd` handler: ```tsx const prevLayout = layout.value; layout.value = measureByTag(e.target); // ... layout.value = prevLayout; ``` This is needed because we need to remember "initial layout" (before keyboard movement) in order to perform beautiful back transition. > I'm more than sure, that this implementation is not perfect and still has some bugs (it is still not clear how to handle a case, when you scroll TextInput off-screen (under keyboard or under header - which back transition do we need to apply in this case?)). But it resolves some of the problems that were reported and shows how to use new API of the library. So in order to unlock a release process I'm leaving this implementation as is - maybe later I'll come up with more sophisticated approach which will handle even more cases, but for now as an example it's good to go. ## 📢 Changelog ### JS - added documentation for `KeyboardAwareScrollView` describing the flow of execution; - removed combination of `useWorkletCallback` + direct `worklet` directive; - interpolate transition based - run additional `scrollTo` in `onEnd` handler to assure that there will be no overlap with `TextInput` and `Keyboard` - handles a case when focus changed, but keyboard size was not changed; - removed `console.log` that were used for debugging 🙂 ## 🤔 How Has This Been Tested? Tested manually on: - iPhone 14 Pro; - Pixel 7 Pro; ## 📸 Screenshots (if appropriate): |Before|After| |------|-----| |<video src="https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/f9e41c28-0082-4dad-8495-57e48ee97c74">|<video src="https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/c43d85ce-0cdb-4bc6-b269-895e3e094ad8">| ## 📝 Checklist - [x] CI successfully passed
- Loading branch information