Search code examples
javascriptreact-nativereact-native-elementsreact-native-paper

How do I show components below textinput when keyboard is open in react native?


I want the tags below the interests textbox to display while the keyboard is open. The chip components are the tags input from the react native paper library. I've tried using scrollview, keyboardavoidingview, and keyboardawarescrollview to get the tags to display while the keyboard is open but none of the views fixed the issue. What would I be missing or doing wrong?

  GetTags = () => {
    const tagsComponent = [];
    if (typeof this.state.interests !== "undefined") {
      for (let i = 0; i < this.state.interests.length; i++) {
        tagsComponent.push(
          <Chip
            key={i}
            style={{ margin: 3 }}
            onClose={() => {
              this.setState(prevState => ({
                interests: prevState.interests.filter(
                  x => x !== prevState.interests[i]
                )
              }));
            }}
          >
            {this.state.interests[i]}
          </Chip>
        );
      }
    }
    return tagsComponent;
  };

  render() {
    const displayTags = this.GetTags();
    return (
      <ScrollView style={{ marginTop: 20 }} keyboardShouldPersistTaps="always">
        <View
          style={{
            flex: 1,
            alignItems: "center",
            justifyContent: "center"
          }}
        >
          {this.state.profile ? (
            <Avatar
              size="xlarge"
              rounded
              source={{ uri: this.state.profile }}
              showEditButton
              onEditPress={() => this.onChooseImageUpload()}
            />
          ) : (
            <Avatar
              {...this.state.avatarError}
              size="xlarge"
              rounded
              icon={{
                name: "user",
                type: "font-awesome"
              }}
              showEditButton
              onEditPress={() => this.onChooseImageUpload()}
            />
          )}
          <Text
            style={{
              fontWeight: "500",
              fontSize: 20,
              marginTop: 8,
              marginRight: "70%",
              color: "#5b5b5b"
            }}
          >
            About me
          </Text>
          <TextInput
            style={{
              borderColor: Themes.layoutTheme,
              borderWidth: 1,
              width: "100%",
              marginTop: 5,
              padding: 5,
              textAlignVertical: "top"
            }}
            multiline
            numberOfLines={7}
            placeholder="Type something about yourself..."
            onChangeText={text => this.setState({ bio: text })}
            value={this.state.bio}
          />
          <View style={{ flexDirection: "row" }}>
            <Text
              style={{
                fontWeight: "500",
                fontSize: 20,
                marginTop: 22,
                color: "#5b5b5b"
              }}
            >
              Interests
            </Text>
            <RNPTextInput
              ref={input}
              style={{
                height: 45,
                marginTop: 10,
                marginRight: 82,
                marginLeft: 10
              }}
              underlineColor={Themes.primaryTheme}
              placeholder="Example: Skydiving,"
              theme={{ colors: { primary: Themes.primaryTheme } }}
              onChangeText={text => {
                if (text.endsWith(",")) {
                  const newText = text.replace(",", "");
                  if (typeof this.state.interests === "undefined") {
                    this.setState({ interests: [newText] });
                  } else {
                    this.setState(prevState => ({
                      interests: [...prevState.interests, newText]
                    }));
                  }
                  input.current.clear();
                }
              }}
            />
          </View>
          <View
            style={{
              marginTop: 15,
              flexDirection: "row",
              flexWrap: "wrap",
              alignItems: "flex-start"
            }}
          >
            {displayTags}
          </View>
          {this.state.loading ? (
            <Progress.Bar
              style={{ marginTop: 25 }}
              indeterminate
              color={Themes.primaryTheme}
            />
          ) : (
            <Button
              raised
              containerStyle={{
                width: "25%",
                marginTop: 20
              }}
              buttonStyle={{ backgroundColor: Themes.primaryTheme }}
              title="Save"
              onPress={() => {
                if (fireStoreDB.getAvatar == null) {
                  this.setState({
                    avatarError: {
                      containerStyle: { borderWidth: 1, borderColor: "red" }
                    }
                  });
                } else {
                  fireStoreDB
                    .updateProfile(this.state.bio, this.state.interests)
                    .then(() => this.props.navigation.navigate("Home"));
                }
              }}
            />
          )}
        </View>
      </ScrollView>
    );
  }


Solution

  • I solved the issue by wrapping content inside KeyboardAvoidingView with the padding behavior and displaying the chips above the text input.

    <KeyboardAvoidingView style={{ flex: 1 }} behavior="padding">
      <Content>
        <View style={{ marginTop: "7%" }} />
        {this.state.profile ? (
          <Avatar
            size="xlarge"
            rounded
            containerStyle={{ alignSelf: "center" }}
            source={{ uri: this.state.profile }}
            showEditButton
            onEditPress={() => this.onChooseImageUpload()}
          />
        ) : (
          <Avatar
            {...this.state.avatarError}
            size="xlarge"
            rounded
            containerStyle={{ alignSelf: "center" }}
            icon={{
              name: "user",
              type: "font-awesome"
            }}
            showEditButton
            onEditPress={() => this.onChooseImageUpload()}
          />
        )}
        <Text
          uppercase={false}
          style={{
            fontWeight: "500",
            fontSize: 20,
            marginTop: "6%",
            marginLeft: "1%",
            color: "#5b5b5b"
          }}
        >
          About me
        </Text>
        <TextInput
          style={{
            borderColor: Themes.layoutTheme,
            borderWidth: 1,
            width: "100%",
            marginTop: 5,
            padding: 5,
            textAlignVertical: "top"
          }}
          multiline
          numberOfLines={7}
          placeholder="Type something about yourself..."
          onChangeText={text => this.setState({ bio: text })}
          value={this.state.bio}
        />
        <Text
          style={{
            fontWeight: "500",
            fontSize: 20,
            marginTop: 22,
            marginLeft: "1.5%",
            color: "#5b5b5b"
          }}
        >
          Interests
        </Text>
        <View
          style={{
            marginTop: 15,
            flexDirection: "row",
            flexWrap: "wrap",
            alignItems: "flex-start"
          }}
        >
          {displayTags}
        </View>
        <Input
          ref={input}
          style
          inputContainerStyle={{
            borderBottomColor: Themes.layoutTheme
          }}
          placeholder="What, are, your, interests"
          onChangeText={text => {
            if (text.endsWith(",")) {
              const newText = text.replace(",", "");
              if (typeof this.state.interests === "undefined") {
                this.setState({ interests: [newText] });
              } else {
                this.setState(prevState => ({
                  interests: [...prevState.interests, newText]
                }));
              }
              input.current.clear();
            }
          }}
        />
      </Content>
    </KeyboardAvoidingView>