mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-24 04:25:34 +08:00
fix: keyboard manager in stack for fast swipe
This commit is contained in:
@@ -11,14 +11,27 @@ type Props = {
|
||||
};
|
||||
|
||||
export default class KeyboardManager extends React.Component<Props> {
|
||||
componentWillUnmount = () => {
|
||||
this.clearKeyboardTimeout();
|
||||
};
|
||||
// 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 keyboardTimeout: NodeJS.Timeout | undefined;
|
||||
|
||||
clearKeyboardTimeout = () => {
|
||||
if (this.keyboardTimeout !== undefined) {
|
||||
clearTimeout(this.keyboardTimeout);
|
||||
this.keyboardTimeout = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
private handlePageChangeStart = () => {
|
||||
if (!this.props.enabled) {
|
||||
return;
|
||||
}
|
||||
this.clearKeyboardTimeout();
|
||||
|
||||
const input = TextInput.State.currentlyFocusedField();
|
||||
|
||||
@@ -27,12 +40,16 @@ 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 = () => {
|
||||
if (!this.props.enabled) {
|
||||
return;
|
||||
}
|
||||
this.clearKeyboardTimeout();
|
||||
|
||||
Keyboard.dismiss();
|
||||
|
||||
@@ -44,15 +61,29 @@ export default class KeyboardManager extends React.Component<Props> {
|
||||
if (!this.props.enabled) {
|
||||
return;
|
||||
}
|
||||
this.clearKeyboardTimeout();
|
||||
|
||||
// The page didn't change, we should restore the focus of text input
|
||||
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) {
|
||||
this.keyboardTimeout = setTimeout(() => {
|
||||
TextInput.State.focusTextInput(input);
|
||||
this.previouslyFocusedTextInput = null;
|
||||
}, 100);
|
||||
} else {
|
||||
TextInput.State.focusTextInput(input);
|
||||
this.previouslyFocusedTextInput = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
Reference in New Issue
Block a user