当TextInput具有自动聚焦属性时,React Native底部表单打开

vyswwuz2  于 2022-11-17  发布在  React
关注(0)|答案(2)|浏览(163)

我使用react-native-bottom-sheet来选择一个类别,当Amount输入具有autofocus属性时,屏幕上会出现下面的表单。

最下面的一张纸出现在键盘后面,它没有按照我想要的捕捉点,它应该在屏幕的中间,但它总是稍微高于键盘。这种情况并不总是发生,像2/5尝试,而且只有当我第一次打开这个屏幕时。工作表应该只在我点击类别时打开,在进入屏幕时应该隐藏。我试着使用一些变量render来检查底部的工作表是否需要渲染,所以我根本不渲染它,但我可以看到它只是闪烁了一秒钟。
这是我的底部表单组件。因为我想创建一个可重用的组件,所以我使用ref将打开底部表单的函数传递给父组件。

const TransactionBottomSheet: React.ForwardRefRenderFunction<refProps, Props> = (props, ref) => {
  const { onSelect } = props;
  const sheetRef = useRef<BottomSheet>(null);
  const [data, setData] = useState<Transaction[]>(categoriesData);
  const [selectedCategory, setSelectedCategory] = useState<Category | null>(null);

  const openSheet = useCallback(() => {
    sheetRef.current?.expand();
  }, []);
  const closeSheet = useCallback(() => {
    sheetRef.current?.close();
  }, []);

  useImperativeHandle(ref, () => ({
    openSheet: () => openSheet(),
  }));

  const setTypeData = (id: number) => {
    const types = transactionCategories[id].types ?? [];
    setData(Object.values(types));
  };

  const clearCategory = () => {
    setData(categoriesData);
    setSelectedCategory(null);
  };

  const onRowPress = (item: Transaction | Category) => {
    if (!selectedCategory) {
      setTypeData(item.id);
      setSelectedCategory(item as Category);
    } else {
      onSelect(selectedCategory, item);
      closeSheet();
    }
  };

  const onClose = () => {
    setData(categoriesData);
    setSelectedCategory(null);
  };

  const renderItem = ({ item }: { item: Transaction | Category }) => (
    <TransactionRowSelect item={item} hideIcon={!!selectedCategory} onPress={onRowPress} />
  );

  const renderBackdrop = useCallback(
    (props) => <BottomSheetBackdrop {...props} disappearsOnIndex={-1} appearsOnIndex={0} />,
    []
  );

  return (
    <BottomSheet
      ref={sheetRef}
      snapPoints={snapPoints}
      enablePanDownToClose
      index={-1}
      onClose={onClose}
      backdropComponent={renderBackdrop}
      handleStyle={styles.handle}
    >
      <Label style={styles.title}>{"Pick category"}</Label>
      {!!selectedCategory && (
        <>
          <TransactionRowSelect item={selectedCategory} onPress={clearCategory} />
          <Separator />
        </>
      )}
      <BottomSheetFlatList
        data={data}
        keyExtractor={(item) => `${item.id}`}
        renderItem={renderItem}
      />
    </BottomSheet>
  );
};

const styles = StyleSheet.create({
  title: {
    textAlign: "center",
    fontSize: 16,
    fontWeight: "bold",
    paddingBottom: 10,
    backgroundColor: colors.grey3,
  },
  handle: {
    backgroundColor: colors.grey3,
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
  },
});

export default React.forwardRef(TransactionBottomSheet);

这是添加交易屏幕

const TransactionForm: React.FC<Props> = ({ navigation }) => {
  const [date, setDate] = useState(new Date());
  const sheetRef = useRef<TransactionBottomSheetType>(null);
  const [category, setCategory] = useState<Category | null>(null);
  const [type, setType] = useState<Transaction | null>(null);
  const [amount, setAmount] = useState("");
  const [description, setDescription] = useState("");

  const [tryCreateNewTransaction, { isLoading }] = useCreateNewTransactionMutation();
  const onAdd = async () => {
    Keyboard.dismiss();
    try {
      if (type && category) {
        await tryCreateNewTransaction({
          amount: Number(amount),
          description,
          date: formatIsoDate(date),
          user_id: 1,
          type_id: type.id,
          category_id: category.id,
        }).unwrap();
        navigation.goBack();
      }
    } catch (error) {
      Alert.alert("An error occurred while adding transaction", "Please try again");
    }
  };

  const onSelectCategory = (category: Category, type: Transaction) => {
    setCategory(category);
    setType(type);
  };

  const setCategoryText = () => {
    if (!category && !type) {
      return "";
    }
    return `${category?.label}, ${type?.label}`;
  };

  const openSheet = () => {
    if (sheetRef?.current) {
      Keyboard.dismiss();
      sheetRef?.current?.openSheet();
    }
  };

  return (
    <View style={styles.container}>
      <DatePickerInput date={date} maximumDate={new Date()} onDateSelect={setDate} />
      // This is just TextInput component with some custom style, here is the autofocus props
      <LabelInput
        value={amount}
        placeholder='Amount'
        onChangeText={setAmount}
        keyboardType='decimal-pad'
        style={styles.marginTop}
        icon={<FontAwesome5 name='coins' size={24} color={colors.greenMint} />}
        autoFocus
      />
      {/* <InputErrorLabel text={errors.amount} isVisible={!!errors.amount} /> */}
      <TouchableOpacity onPress={openSheet}>
        <LabelInput
          value={setCategoryText()}
          icon={<MaterialIcons name='category' size={24} color={colors.greenMint} />}
          disabled
          placeholder='Category'
          style={styles.marginTop}
          inputStyle={styles.category}
        />
      </TouchableOpacity>
      <TextBox
        placeholder='Transaction comment'
        style={styles.marginTop}
        numberOfLines={6}
        maxLength={300}
        value={description}
        onChangeText={setDescription}
      />
      <CustomButton title='Submit' onPress={onAdd} style={styles.marginTop} />
      <AppActivityIndicator isLoading={isLoading} />
      <TransactionBottomSheet ref={sheetRef} onSelect={onSelectCategory} />
    </View>
  );
};

export default TransactionForm;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingHorizontal: 16,
    paddingTop: 20,
  },
  marginTop: {
    marginTop: 20,
  },
  category: {
    color: colors.black,
  },
});
ulydmbyx

ulydmbyx1#

找到了一个解决这个问题的方法,它看起来像是与键盘和expo有关。我注意到当键盘被显示或关闭时,有一个白色的背景在它后面显示了一瞬间。我通过将这个添加到app.json来修复这个问题

"android": {
      "softwareKeyboardLayoutMode": "pan"
    },

这也解决了键盘和底板的问题。没有看到它出现了。

zc0qhyus

zc0qhyus2#

听键盘show/hide的声音,然后对底部表单做任何你想做的事情。例如,这里我改变了底部表单的捕捉点。

React.useEffect(() => {

    let keyboardHideListener = Keyboard.addListener('keyboardDidHide', () => {
      if (isBottomSheetOpen.current) {
        bottomSheetRef.current?.snapToIndex(0);
      }
    });

    let keyboardShowListener = Keyboard.addListener('keyboardDidShow', () => {
      if (isBottomSheetOpen.current) {
        bottomSheetRef.current?.snapToIndex(1);
      }
    });

    return () => {
      keyboardHideListener.remove();
      keyboardShowListener.remove();
    };

  }, []);

相关问题