1、输入框 + clear按钮 不关闭键盘
RN的默认行为: scrollview + textinput + 自定义的清除按钮,输入框获焦的时候 弹起键盘,此时点击清空按钮的时候会先关闭弹框,需要再次点击清除按钮才会清空输入框。
观察原生app的输入框可以 点击清空按钮的时候 输入框还是获焦状态 而且键盘没有关闭,然后摸索实现方式。
方式一:失焦再获焦,这样会让键盘有关闭动作再升起来,效果虽然达到了,但是还差一些意思。
ts
export default function SearchInput() {
const [text, setText] = useState('');
const inputRef = useRef<TextInput>(null);
const handleClear = () => {
setText('');
// 立即重新聚焦
requestAnimationFrame(() => {
inputRef.current?.focus();
});
};
return (
<View style={styles.container}>
<TextInput ref={inputRef} style={styles.input} value={text} onChangeText={setText} placeholder="输入内容..." />
{text.length > 0 && (
<TouchableOpacity
style={styles.closeButton}
onPress={handleClear}
activeOpacity={0.7}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
>
<Text style={styles.closeText}>×</Text>
</TouchableOpacity>
)}
</View>
);
}
方式二:使用react-native-gesture-handler自带的Pressable组件,它运行在原生线程上,不会触发 JS 线程的失焦事件,完美的达到我需要的效果。
ts
import React, { useRef, useState } from 'react';
import { StyleSheet, View, TextInput, Text } from 'react-native';
// 主要是这里的 Pressable组件!
import { Pressable } from 'react-native-gesture-handler';
export default function SearchInput() {
const [text, setText] = useState('');
const inputRef = useRef<TextInput>(null);
const handleClear = () => {
setText('');
};
return (
<View style={styles.container}>
<TextInput ref={inputRef} style={styles.input} value={text} onChangeText={setText} placeholder="输入内容..." />
{text.length > 0 && (
<Pressable
style={styles.closeButton}
onPress={handleClear}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
>
<Text style={styles.closeText}>×</Text>
</Pressable>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: COLORS.white,
borderRadius: scaleLinear(9),
paddingHorizontal: scaleLinear(SPACING.md),
height: scaleLinear(38),
borderWidth: 1,
borderColor: COLORS.gray4,
},
input: {
flex: 1,
fontSize: scaleLinear(14),
color: COLORS.textPrimary,
paddingVertical: 0,
},
closeButton: {
width: scaleLinear(24),
height: scaleLinear(24),
borderRadius: scaleLinear(12),
backgroundColor: COLORS.gray1,
alignItems: 'center',
justifyContent: 'center',
marginLeft: scaleLinear(4),
},
closeText: {
fontSize: scaleLinear(16),
color: COLORS.textSecondary,
textAlign: 'center',
lineHeight: scaleLinear(22),
},
});