88 lines
2.0 KiB
TypeScript
88 lines
2.0 KiB
TypeScript
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
|
|
import { useRef, useState } from "react";
|
|
import { Animated, Easing, StyleSheet, TextInput } from "react-native";
|
|
|
|
type ConversationSearchBarProps = {
|
|
value: string;
|
|
onChangeText: (value: string) => void;
|
|
};
|
|
|
|
export function ConversationSearchBar({
|
|
value,
|
|
onChangeText,
|
|
}: ConversationSearchBarProps) {
|
|
const [isFocused, setIsFocused] = useState(false);
|
|
const focusAnim = useRef(new Animated.Value(0)).current;
|
|
|
|
const animateFocus = (toValue: 0 | 1) => {
|
|
Animated.timing(focusAnim, {
|
|
toValue,
|
|
duration: 140,
|
|
easing: Easing.out(Easing.quad),
|
|
useNativeDriver: true,
|
|
}).start();
|
|
};
|
|
|
|
return (
|
|
<Animated.View
|
|
style={[
|
|
styles.wrapper,
|
|
isFocused && styles.wrapperFocused,
|
|
{
|
|
transform: [
|
|
{
|
|
scale: focusAnim.interpolate({
|
|
inputRange: [0, 1],
|
|
outputRange: [1, 1.01],
|
|
}),
|
|
},
|
|
],
|
|
},
|
|
]}
|
|
>
|
|
<MaterialIcons color="#A2A2A7" name="search" size={28} />
|
|
<TextInput
|
|
onBlur={() => {
|
|
setIsFocused(false);
|
|
animateFocus(0);
|
|
}}
|
|
onChangeText={onChangeText}
|
|
onFocus={() => {
|
|
setIsFocused(true);
|
|
animateFocus(1);
|
|
}}
|
|
placeholder="搜索联系人备注/昵称/ID"
|
|
placeholderTextColor="#B8B8BC"
|
|
style={styles.input}
|
|
value={value}
|
|
/>
|
|
</Animated.View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
wrapper: {
|
|
alignItems: "center",
|
|
backgroundColor: "#F0F0F2",
|
|
borderColor: "transparent",
|
|
borderCurve: "continuous",
|
|
borderWidth: 1,
|
|
borderRadius: 20,
|
|
flexDirection: "row",
|
|
gap: 8,
|
|
height: 52,
|
|
marginHorizontal: 20,
|
|
paddingHorizontal: 16,
|
|
},
|
|
wrapperFocused: {
|
|
backgroundColor: "#F4FAF8",
|
|
borderColor: "#BEEEDB",
|
|
},
|
|
input: {
|
|
color: "#2A2A2A",
|
|
flex: 1,
|
|
fontSize: 16,
|
|
fontWeight: "400",
|
|
},
|
|
});
|