Skip to content

Commit

Permalink
fix: KeyboardAvoidingView height when "Prefer Cross-Fade Transitions"…
Browse files Browse the repository at this point in the history
… is enabled (facebook#34503)

Summary:
Fix `KeyboardAvoidingView`  height on iOS when "Prefer Cross-Fade Transitions" is enabled by adding an additional check to `_relativeKeyboardHeight` verifying if `prefersCrossFadeTransitions()` is true and `keyboardFrame.screenY` is `0` and treating this special case. The issue was caused  by the native RCTKeyboardObserver where the `endFrame` reported by `UIKeyboardWillChangeFrameNotification` returns `height = 0` when Prefer Cross-Fade Transitions" is enabled
and unfortunelly there isn't much we can do on the native side to fix it.

Closes facebook#31484
Closes facebook#29974

## Changelog

[iOS] [Fixed] - Fix KeyboardAvoidingView height when "Prefer Cross-Fade Transitions" is enabled

Pull Request resolved: facebook#34503

Test Plan:
**On iOS 14+**

1.  Access Settings > "General" > "Accessibility" > "Reduce Motion", enable "Reduce Motion" then enable "Prefer Cross-Fade Transitions".
2. Open the RNTester app and navigate to the KeyboardAvoidingView page
3. Focus and blur inputs and observe the keyboard behaving correctly

https://user-images.githubusercontent.com/11707729/186822671-801872be-7db1-4c5c-904b-1987441c1326.mov

Reviewed By: jacdebug

Differential Revision: D39055213

Pulled By: cipolleschi

fbshipit-source-id: fac17cbe02867e0fe522397f6cb59a8b51c1840f
  • Loading branch information
gabrieldonadel authored and facebook-github-bot committed Aug 31, 2022
1 parent 7a6f0e4 commit 4b9382c
Showing 1 changed file with 18 additions and 5 deletions.
23 changes: 18 additions & 5 deletions Libraries/Components/Keyboard/KeyboardAvoidingView.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type {
ViewLayoutEvent,
} from '../View/ViewPropTypes';
import type {KeyboardEvent, KeyboardMetrics} from './Keyboard';
import AccessibilityInfo from '../AccessibilityInfo/AccessibilityInfo';

type Props = $ReadOnly<{|
...ViewProps,
Expand Down Expand Up @@ -71,12 +72,24 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
this.viewRef = React.createRef();
}

_relativeKeyboardHeight(keyboardFrame: KeyboardMetrics): number {
async _relativeKeyboardHeight(
keyboardFrame: KeyboardMetrics,
): Promise<number> {
const frame = this._frame;
if (!frame || !keyboardFrame) {
return 0;
}

// On iOS when Prefer Cross-Fade Transitions is enabled, the keyboard position
// & height is reported differently (0 instead of Y position value matching height of frame)
if (
Platform.OS === 'ios' &&
keyboardFrame.screenY === 0 &&
(await AccessibilityInfo.prefersCrossFadeTransitions())
) {
return 0;
}

const keyboardY =
keyboardFrame.screenY - (this.props.keyboardVerticalOffset ?? 0);

Expand All @@ -90,7 +103,7 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
this._updateBottomIfNecessary();
};

_onLayout = (event: ViewLayoutEvent) => {
_onLayout = async (event: ViewLayoutEvent) => {
const wasFrameNull = this._frame == null;
this._frame = event.nativeEvent.layout;
if (!this._initialFrameHeight) {
Expand All @@ -99,22 +112,22 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
}

if (wasFrameNull) {
this._updateBottomIfNecessary();
await this._updateBottomIfNecessary();
}

if (this.props.onLayout) {
this.props.onLayout(event);
}
};

_updateBottomIfNecessary = () => {
_updateBottomIfNecessary = async () => {
if (this._keyboardEvent == null) {
this.setState({bottom: 0});
return;
}

const {duration, easing, endCoordinates} = this._keyboardEvent;
const height = this._relativeKeyboardHeight(endCoordinates);
const height = await this._relativeKeyboardHeight(endCoordinates);

if (this.state.bottom === height) {
return;
Expand Down

0 comments on commit 4b9382c

Please sign in to comment.