Skip to content
This repository has been archived by the owner on Feb 25, 2020. It is now read-only.

Commit

Permalink
fix: handle keyboard return for short interactions (#272)
Browse files Browse the repository at this point in the history
When user has super short swiping interaction it's an issue that keyboard won't reappear on screen.
That's because there is short time when system will make sure to hide keyboard no matter what. Too fast text input refocus will result only in keyboard flashing on screen and hiding right away.

For such short interactions I created a delay that will ensure that the keyboard will reappear on the screen every time and make sure it's executed only when needed.
It only affect super short interactions <100ms to make sure they work correctly, and doesn't affect any logic beyond that.

As far as my research go it seems that the react-navigation isn't responsible for hiding the Keyboard in that specific case, so I don't think we can simply prevent this action when we don't want it. Doing the check in KeyboardMenager and delaying it is the safest way IMO - we make sure that it won't affect any other logic than concerning keyboard itself. (It would happen if we prevent the action somewhere else like in StackItem)

Tested on physical iOS device, iOS simulator, and Android device with both app using the library and library's example app.
  • Loading branch information
wojtus7 authored and osdnk committed Oct 23, 2019
1 parent dd24ce8 commit 35cc5b8
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions src/views/KeyboardManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default class KeyboardManager extends React.Component<Props> {
// Numeric id of the previously focused text input
// When a gesture didn't change the tab, we can restore the focused input with this
private previouslyFocusedTextInput: number | null = null;
private startTimestamp: number = 0;

private handlePageChangeStart = () => {
const input = TextInput.State.currentlyFocusedField();
Expand All @@ -22,6 +23,9 @@ export default class KeyboardManager extends React.Component<Props> {

// Store the id of this input so we can refocus it if change was cancelled
this.previouslyFocusedTextInput = input;

// Store timestamp for touch start
this.startTimestamp = Date.now();
};

private handlePageChangeConfirm = () => {
Expand All @@ -36,10 +40,23 @@ export default class KeyboardManager extends React.Component<Props> {
const input = this.previouslyFocusedTextInput;

if (input) {
TextInput.State.focusTextInput(input);
}
// If the interaction was super short we should make sure keyboard won't hide again.

this.previouslyFocusedTextInput = null;
// Too fast input refocus will result only in keyboard flashing on screen and hiding right away.
// During first ~100ms keyboard will be dismissed no matter what,
// so we have to make sure it won't interrupt input refocus logic.
// That's why when the interaction is shorter than 100ms we add delay so it won't hide once again.
// Subtracting timestamps makes us sure the delay is executed only when needed.
if (Date.now() - this.startTimestamp < 100) {
setTimeout(() => {
TextInput.State.focusTextInput(input);
this.previouslyFocusedTextInput = null;
}, 100);
} else {
TextInput.State.focusTextInput(input);
this.previouslyFocusedTextInput = null;
}
}
};

render() {
Expand Down

0 comments on commit 35cc5b8

Please sign in to comment.