React Native KeyboardAvoidingView 无法正确移动

Adr*_*scu 8 javascript react-native

我有一个TextInput按下时会被键盘覆盖的东西。所以我把它包裹在一个KeyboardAvoidingView. 但无论我为此视图设置什么行为,都TextInput不会在键盘上方移动。使用positionas 行为移动TextInput但仅位于键盘上方的一半位置,而其他两个似乎根本不起作用。

我还尝试用 包装整个组件KeyboardAvoidingView,但这样做会破坏整个布局。

谁能帮我?我从来没有设法KeyboardAvoidingView为自己工作,现在我真的需要它。提前致谢!

这是我的组件。另外值得一提的是,这个组件是顶级的(嗯,几乎是顶级的,因为它包含在路由器中)

const { height, width } = Dimensions.get('screen')

const style = StyleSheet.create({
    main: {
        height,
        width,
        flexDirection: 'column',
    },
    iconSelecter: {
        width,
        height: 196,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: Colors.primary,
        marginTop: 32
    },
    icon: {
        height: 164,
        width: 164,
    },
    saveButton: {
        width: 96,
        height: 96,
        borderRadius: 100,
        backgroundColor: Colors.secondary,
        alignItems: "center",
        justifyContent: "center",
        alignSelf: 'center',
        position: 'absolute',
        bottom: 96 + 32
    },
    saveIcon: {
        height: 54,
        width: 54,
    },
    textInputWrapper: {
        borderBottomColor: Colors.textInputBorder,
        width: 288,
        borderBottomWidth: 1,
        alignSelf: 'center',
        marginTop: 96,
        height: 48,
    },
    textInput: {
        fontWeight: "300",
        fontSize: 14,
        margin: 0
    },
    hintWrapper: {
        alignSelf: 'center',
        marginTop: 4
    },
    hint: {
        fontSize: 12,
        fontFamily: "Roboto-Thin",
        fontStyle: 'normal',
    }
})


    const CreateActivity = ({ goBack }: NavigationProps) => {

    //////////////////////////////
    //State and logic 
    ///////////////


        return (
            // TODO: Add touchable opacity to dismiss keyboard

            <View style={style.main}>
                <Appbar title="New activity" canGoBack goBack={goBack} />
                <View style={{ flex: 1 }}>
                    <View style={style.iconSelecter}>
                        <GestureRecognizer onSwipeLeft={nextIcon} onSwipeRight={lastIcon}>
                            <Image style={style.icon} source={icons[currentIconIndex]?.file}></Image>
                        </GestureRecognizer>
                    </View>
                    <View style={style.hintWrapper}>
                        <Text style={style.hint}>Swipe to cycle through the icons</Text>
                    </View>

                    <KeyboardAvoidingView>
                        <View style={style.textInputWrapper}>
                            <TextInput style={style.textInput} placeholder={"Give this activity a name"} value={name} onChangeText={setName}></TextInput>
                        </View>
                    </KeyboardAvoidingView>
                    <TouchableNativeFeedback onPress={createActivity} background={TouchableNativeFeedback.Ripple("#fff", true)}>
                        <View style={style.saveButton}>
                            <Image style={style.saveIcon} source={require("../../assets/icons/light/save.png")}></Image>
                        </View>
                    </TouchableNativeFeedback>
                </View>
            </View>

        )
    }


    export default CreateActivity;
Run Code Online (Sandbox Code Playgroud)

Bru*_*ras 6

我建议您尝试将屏幕的所有内容包裹起来<KeyboardAvoidingView />(或使其成为最外面的元素之一),否则它只会向上滑动其子元素(View 和 TextInput),而将其余内容保留在其原始位置,使布局看起来重叠且奇怪。如果你这样做,“位置”值应该可以正常工作。

像这样的东西:

<View style={style.main}>
    <Appbar title="New activity" canGoBack goBack={goBack} />
    <KeyboardAvoidingView behavior="position" >
      <View style={{ flex: 1 }}> // --> Remove flex: 1 if you experience some issue with the positioning
          <View style={style.iconSelecter}>
              <GestureRecognizer onSwipeLeft={nextIcon} onSwipeRight={lastIcon}>
                  <Image style={style.icon} source={icons[currentIconIndex]?.file}></Image>
              </GestureRecognizer>
          </View>
          <View style={style.hintWrapper}>
              <Text style={style.hint}>Swipe to cycle through the icons</Text>
          </View>

          <KeyboardAvoidingView>
              <View style={style.textInputWrapper}>
                  <TextInput style={style.textInput} placeholder={"Give this activity a name"} value={name} onChangeText={setName}></TextInput>
              </View>
          </KeyboardAvoidingView>
          <TouchableNativeFeedback onPress={createActivity} background={TouchableNativeFeedback.Ripple("#fff", true)}>
              <View style={style.saveButton}>
                  <Image style={style.saveIcon} source={require("../../assets/icons/light/save.png")}></Image>
              </View>
          </TouchableNativeFeedback>
      </View>
    </KeyboardAvoidingView>
</View>
Run Code Online (Sandbox Code Playgroud)

另请参阅上面代码中的注释。检查您是否确实需要在所有外部包装元素中使用 flex: 1,并查看您在基于尺寸height中设置的内容。style.main我认为这是没有必要的,并且如果您修复父容器的高度,可能会导致一些测量问题。

编辑:

我只是在研究 React-Native 文档,我意识到有一个 zIndex 可以用来避免绝对定位。它是一个相对样式属性,因此需要在同级视图之间设置,如下所示:

export default class MyComponent extends React.Component {
  render() {
    return (
      <View>
        <View style={[styles.appbarShape, styles.appbarZIndex]} ><Text>Header</Text></View>
        <KeyboardAvoidingView behavior="position" style={styles.contentZIndex}>
          {other children}
          <TextInput placeholder="enter text"/>
        </KeyboardAvoidingView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  appbarShape: {
    height: 80,
    width: Dimensions.get('window').width,
    justifyContent: 'center',
    alignSelf: "stretch",
    backgroundColor: "#FFF"
  },
  appbarZIndex: {
    zIndex: 3,
  },
  contentZIndex: {
    zIndex: 0
  }
});
Run Code Online (Sandbox Code Playgroud)

由于代表应用程序栏的视图具有更大的 zIndex,因此它会显示在 zIndex 较低的视图之上,请检查此小吃中的工作https://snack.expo.io/5VXAcw4Y0

文档: https: //reactnative.dev/docs/layout-props

希望能帮助到你!