React Native 中实现折叠联动输入框组

185 阅读1分钟

折叠输入框(组)

需求描述:

希望在输入框收起时能够直接按照username@host:port的格式输入,在展开时能够自动将输入拆分为usernamehostport显示在子输入框,且能够在顶部的输入框同步子输入框组输入数据的拼合值;此外还需要处理输入为空或不符合格式的特殊情况。

实现如下:

const [combine, onChangeCombine] = React.useState("");
const [username, onChangeUsername] = React.useState("");
const [host, onChangeHost] = React.useState("");
const [port, onChangePort] = React.useState("");

const [isMenuVisible_Setting, setIsMenuVisible_Setting] = useState(false);

const handleSet_Setting = () => {

  if (!isMenuVisible_Setting) { //如果要展开:拆分输入值,在子输入框中展示
    const parts = combine.split(/[@:]/);
    onChangeUsername(parts[0] || "");
    onChangeHost(parts[1] || "");
    onChangePort(parts[2] || "");
  } else if(username||host||port) //如果要收起,且子输入框不全为空:拼合输入值
    onChangeCombine(username + "@" + host + ":" + port);
  else onChangeCombine(""); //如果要收起,且子输入框为空:设为空

  setIsMenuVisible_Setting(!isMenuVisible_Setting);
};
<View style={styles.item}>
  <View style={{ display: "flex", flexDirection: "column", width: "100%" }}>

    <View style={styles.accordionContainer}>
      <View style={styles.accordionHeader}>
        <TextInput
          style={styles.input}
          onChangeText={text => {onChangeCombine(text)}}
          value={isMenuVisible_Setting ? (username || host || port ? username + "@" + host + ":" + port : "") : combine}
          placeholder={"用户名@主机:端口"}
          editable={!isMenuVisible_Setting} /*展开时顶部输入框不可编辑,显示临时拼合值*/
        />
        <TouchableOpacity activeOpacity={0.5} onPress={handleSet_Setting} style={styles.arrow}>
          <Text style={{ fontSize: 20 }}>{isMenuVisible_Setting ? "▲" : "▼"}</Text>
        </TouchableOpacity>
      </View>

      {isMenuVisible_Setting && <View style={styles.accordionContent}>
        {<><TextInput
          style={styles.input}
          onChangeText={text => onChangeUsername(text)}
          value={username || ""}
          placeholder={"用户名"}
        /><TextInput
          style={styles.input}
          onChangeText={text => onChangeHost(text)}
          value={host || ""}
          placeholder={"主机"}
        /><TextInput
          style={styles.input}
          onChangeText={text => onChangePort(text)}
          value={port || ""}
          placeholder={"端口"}
        /></>}
      </View>}
    </View>
  </View>
</View>
const screenWidth = Dimensions.get("window").width;

const styles = StyleSheet.create({
  item: {
    minHeight: 80,
    flexDirection: "row",
    justifyContent: "flex-start",
    alignItems: "center",
    borderBottomWidth: 1,
    borderBottomColor: "black",
  },
  input: {
    height: 50,
    width: screenWidth - 60,
		margin: 5,
    lineHeight: 25,
    borderColor: "gray",
    borderWidth: 1,
  },
  accordionContainer: {
    overflow: "hidden"
  },
  accordionHeader: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    padding: 10
  },
  accordionContent: {
    padding: 10,
    backgroundColor: "#ffffff"
  },
  arrowContainer: {
    width: "auto",
    position: "absolute",
    right: 0,
    display: "flex",
    fontSize: 20,
  },
  arrow: {
    position: "absolute",
    fontSize: 20,
    marginTop: -10,
    right: 15,
  },
});

效果示例:(样式经过美化)

2023-10-18 14 45 38.gif

2023-10-18 14 45 10.gif