mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix <KeyboardAvoidingView> with floating keyboard on iPad (#44859)
Summary:
On iPadOS, users can change the kind of keyboard displayed onscreen, going from normal keyboard, to split keyboard (one half on the left of the screen, one half on the right), or a floating keyboard that you can move around the screen.
When a non-normal kind of keyboard is used, `<KeyboardAvoidingView>` calculations are all wrong and, depending on the `behavior` prop, can make your screen completely hidden.
This PR attempts to detect that the keyboard is not the "normal displayed-at-bottom-of-screen" keyboard, and forces `enable={false}` if this happens.
The approach of comparing the keyboard width with the window width comes from this comment: https://github.com/facebook/react-native/issues/29473#issuecomment-696658937
A better fix might be to detect the kind of keyboard used, but this involves native code changes and I do not know iOS enough to do that. In addition, I have not found an easy way to do it using iOS APIs after a quick search.
I also chose to cache the window width as a class attribute. Maybe this is not needed as `Dimensions.get('window').width` is very fast and can be called on every keyboard event?
This fixes https://github.com/facebook/react-native/issues/44068 and https://github.com/facebook/react-native/issues/29473
[IOS] [FIXED] - Fix `<KeyboardAvoidingView>` with floating keyboard on iPadOS
Pull Request resolved: https://github.com/facebook/react-native/pull/44859
Test Plan:
Tested using RNTester and the "Keyboard Avoiding View with different behaviors" example.
Before:
https://github.com/facebook/react-native/assets/42070/111598a3-286c-464d-8db8-73afb35cd7f9
After:
https://github.com/facebook/react-native/assets/42070/0b3bc94f-8b67-4f42-8a83-e11555080268
Reviewed By: cortinico
Differential Revision: D62844854
Pulled By: cipolleschi
fbshipit-source-id: 577444be50019572955a013969d78178914b5b8d
This commit is contained in:
committed by
Riccardo Cipolleschi
parent
069d8fc249
commit
0e677ed243
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
|
||||
import type {DimensionsPayload} from '../../Utilities/NativeDeviceInfo';
|
||||
import type {
|
||||
ViewLayout,
|
||||
ViewLayoutEvent,
|
||||
@@ -18,6 +19,7 @@ import type {KeyboardEvent, KeyboardMetrics} from './Keyboard';
|
||||
|
||||
import LayoutAnimation from '../../LayoutAnimation/LayoutAnimation';
|
||||
import StyleSheet from '../../StyleSheet/StyleSheet';
|
||||
import Dimensions from '../../Utilities/Dimensions';
|
||||
import Platform from '../../Utilities/Platform';
|
||||
import {type EventSubscription} from '../../vendor/emitter/EventEmitter';
|
||||
import AccessibilityInfo from '../AccessibilityInfo/AccessibilityInfo';
|
||||
@@ -66,6 +68,7 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
|
||||
viewRef: {current: React.ElementRef<typeof View> | null, ...};
|
||||
_initialFrameHeight: number = 0;
|
||||
_bottom: number = 0;
|
||||
_windowWidth: number = Dimensions.get('window').width;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
@@ -130,6 +133,10 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
|
||||
}
|
||||
};
|
||||
|
||||
_onDimensionsChange = ({window}: DimensionsPayload) => {
|
||||
this._windowWidth = window?.width ?? 0;
|
||||
};
|
||||
|
||||
// Avoid unnecessary renders if the KeyboardAvoidingView is disabled.
|
||||
_setBottom = (value: number) => {
|
||||
const enabled = this.props.enabled ?? true;
|
||||
@@ -145,6 +152,15 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
Platform.OS === 'ios' &&
|
||||
this._windowWidth !== this._keyboardEvent.endCoordinates.width
|
||||
) {
|
||||
// The keyboard is not the standard bottom-of-the-screen keyboard. For example, floating keyboard on iPadOS.
|
||||
this._setBottom(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const {duration, easing, endCoordinates} = this._keyboardEvent;
|
||||
const height = await this._relativeKeyboardHeight(endCoordinates);
|
||||
|
||||
@@ -178,6 +194,7 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
|
||||
if (Platform.OS === 'ios') {
|
||||
this._subscriptions = [
|
||||
Keyboard.addListener('keyboardWillChangeFrame', this._onKeyboardChange),
|
||||
Dimensions.addEventListener('change', this._onDimensionsChange),
|
||||
];
|
||||
} else {
|
||||
this._subscriptions = [
|
||||
|
||||
Reference in New Issue
Block a user