@mpxjs/webpack-plugin
Version:
mpx compile core
94 lines (93 loc) • 4.44 kB
JSX
import React, { useContext, useEffect } from 'react';
import { Keyboard, View } from 'react-native';
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
import { KeyboardAvoidContext } from './context';
import { isIOS } from './utils';
const KeyboardAvoidingView = ({ children, style, contentContainerStyle }) => {
const duration = isIOS ? 250 : 300;
const easing = isIOS ? Easing.inOut(Easing.ease) : Easing.out(Easing.quad);
const offset = useSharedValue(0);
const basic = useSharedValue('auto');
const keyboardAvoid = useContext(KeyboardAvoidContext);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ translateY: -offset.value }],
flexBasis: basic.value
}));
const resetKeyboard = () => {
if (keyboardAvoid?.current) {
keyboardAvoid.current = null;
}
offset.value = withTiming(0, { duration, easing });
basic.value = 'auto';
};
const onTouchEnd = ({ nativeEvent }) => {
if (nativeEvent.origin !== 'input') {
Keyboard.isVisible() && Keyboard.dismiss();
}
};
useEffect(() => {
let subscriptions = [];
if (isIOS) {
subscriptions = [
Keyboard.addListener('keyboardWillShow', (evt) => {
if (!keyboardAvoid?.current)
return;
const { endCoordinates } = evt;
const { ref, cursorSpacing = 0 } = keyboardAvoid.current;
setTimeout(() => {
ref?.current?.measure((x, y, width, height, pageX, pageY) => {
const aboveOffset = offset.value + pageY + height - endCoordinates.screenY;
const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing;
const belowValue = Math.min(endCoordinates.height, aboveOffset + cursorSpacing);
const value = aboveOffset > 0 ? belowValue : aboveValue;
offset.value = withTiming(value, { duration, easing }, (finished) => {
if (finished) {
// Set flexBasic after animation to trigger re-layout and reset layout information
basic.value = '99.99%';
}
});
});
});
}),
Keyboard.addListener('keyboardWillHide', resetKeyboard)
];
}
else {
subscriptions = [
Keyboard.addListener('keyboardDidShow', (evt) => {
if (!keyboardAvoid?.current)
return;
const { endCoordinates } = evt;
const { ref, cursorSpacing = 0 } = keyboardAvoid.current;
ref?.current?.measure((x, y, width, height, pageX, pageY) => {
const aboveOffset = pageY + height - endCoordinates.screenY;
const belowOffset = endCoordinates.height - aboveOffset;
const aboveValue = -aboveOffset >= cursorSpacing ? 0 : aboveOffset + cursorSpacing;
const belowValue = Math.min(belowOffset, cursorSpacing);
const value = aboveOffset > 0 ? belowValue : aboveValue;
offset.value = withTiming(value, { duration, easing }, (finished) => {
if (finished) {
// Set flexBasic after animation to trigger re-layout and reset layout information
basic.value = '99.99%';
}
});
});
}),
Keyboard.addListener('keyboardDidHide', resetKeyboard)
];
}
return () => {
subscriptions.forEach(subscription => subscription.remove());
};
}, [keyboardAvoid]);
return (<View style={style} onTouchEnd={onTouchEnd}>
<Animated.View style={[
contentContainerStyle,
animatedStyle
]}>
{children}
</Animated.View>
</View>);
};
KeyboardAvoidingView.displayName = 'MpxKeyboardAvoidingView';
export default KeyboardAvoidingView;