Reputation: 633
So I have a restaurant listing with a filter at the top and below that the restaurants are updated as you type to match your filter. When your filter does not return anything the view is then changed to show a "No restaurants found, change your filter" type message. I have this set up as a KeyboardAvoidingView because I wanted it centered vertically, and when you have the keyboard open it's sitting just barely above it, and doesn't look great. With the view active however it's pushed up a bit and becomes centered with what is visible.
My problem is that once the filter is used enough to hide all restaurants, the KAV is then shown in the render function but doesn't recognize that the keyboard is open and it needs to move. If I get to that stage and then close/re-open the keyboard it works, but that is far from ideal.
I've already checked out this thread and tried the solution found there: KeyboardAvoidingView - Reset height when Keyboard is hidden but that did not work for me unfortunately.
And this thread seems to have the same problem as I do: react native KeyboardAvoidingView with already opened keyboard dont work properly but the solution was to hide the keyboard, which I do not want. I want them to correct their input and reduce the filter immediately using the already-open keyboard.
Is there a way I can introduce the KAV after the keyboard is already open and have it react to the already-opened keyboard?
Upvotes: 1
Views: 782
Reputation: 11
UPDATE: Try to use this lib instead: https://github.com/kirillzyusko/react-native-keyboard-controller It solved a lot of our problems.
This is what worked for us
import { useEffect, useState } from 'react';
import { Keyboard } from 'react-native';
export const useKeyboardVisible = () => {
const [isKeyboardWillHide, setKeyboardWillHide] = useState(false);
useEffect(() => {
const keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', () => {
setKeyboardWillHide(true);
});
return () => {
keyboardWillHideListener.remove();
};
}, []);
return { isKeyboardWillHide };
};
marginBottom
styles (for smooth layout change):Keyboard.isVisible();
;Keyboard.metrics()
;marginBottom
= keyboard height
import { Keyboard } from 'react-native';
import { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
const useKeyboardAlreadyVisibleMarginFix = () => {
const { isKeyboardWillHide } = useKeyboardVisible();
const marginBottom = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => {
return {
marginBottom: marginBottom.value
? marginBottom.value
: withTiming(0, {
duration: 300,
}),
};
}, []);
useEffect(() => {
const isVisible = Keyboard.isVisible();
const metrics = Keyboard.metrics();
if (isVisible) {
marginBottom.value = metrics?.height ?? 0;
}
if (isKeyboardWillHide) {
marginBottom.value = 0;
}
return () => {
marginBottom.value = 0;
};
}, [isKeyboardWillHide, marginBottom]);
return { animatedStyle };
};
import { Keyboard, KeyboardAvoidingView, Platform } from 'react-native';
import { useHeaderHeight } from '@react-navigation/elements';
import Animated from 'react-native-reanimated';
// ...
const height = useHeaderHeight();
const { animatedStyle } = useKeyboardAlreadyVisibleMarginFix();
if (Platform.OS === 'ios') {
return (
<KeyboardAvoidingView behavior="padding" style={{flex: 1}} keyboardVerticalOffset={height}>
<Animated.View style={[{ flex: 1 }, animatedStyle]}>{children}</Animated.View>
</KeyboardAvoidingView>
);
}
Upvotes: 1