React Native 当键盘已经打开并且render()更新为显示KeyboardAvoidingView(之前没有显示)时,它不会避开键盘

gz5pxeao  于 2023-06-24  发布在  React
关注(0)|答案(1)|浏览(113)

所以我有一个餐厅列表,在顶部和下面有一个过滤器,当你输入匹配你的过滤器时,餐厅会更新。当您的过滤器没有返回任何内容时,视图将更改为显示“未找到餐厅,请更改您的过滤器”类型的消息。我把这个设置为KeyboardAvoidingView,因为我想让它垂直居中,当你打开键盘时,它就在它上面,看起来不太好。然而,在视图处于活动状态时,它会被向上推一点,并与可见的内容居中。
我的问题是,一旦过滤器被用来隐藏所有的餐馆,KAV然后显示在渲染功能,但不承认键盘是打开的,它需要移动。如果我到了那个阶段,然后关闭/重新打开键盘,它就可以工作了,但这远非理想。
我已经检查了这个线程,并尝试了在那里找到的解决方案:KeyboardAvoidingView - Reset height when Keyboard is hidden但不幸的是,这对我不起作用。
这篇文章似乎和我有同样的问题:react native KeyboardAvoidingView with already opened keyboard dont work properly但解决方案是隐藏键盘,这是我不想要的。我想让他们纠正他们的输入,并立即使用已经打开的键盘减少过滤。
有没有一种方法可以在键盘已经打开后引入KAV,并让它对已经打开的键盘做出React?

mwkjh3gx

mwkjh3gx1#

这就是我们的工作
1.我们需要创建一个钩子,告诉我们键盘将隐藏(我们稍后会需要它):

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 };
};

1.接下来,我们需要创建一个钩子,它将返回我们的动画marginBottom样式(用于平滑的布局更改):

  • 使用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 };
};

1.使用`Animated.View使布局动画更加人性化:

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>
   );
}

相关问题