2025-06-26 15:12:34 +08:00

117 lines
4.0 KiB
TypeScript

import React, { useRef, useState } from 'react';
import { Animated, Keyboard, Text, TextInput, TouchableOpacity, View } from 'react-native';
const VerificationCodeInput = () => {
const [code, setCode] = useState(['', '', '', '', '', '']);
const refs = useRef([]);
const shakeAnim = useRef(new Animated.Value(0)).current;
const focusNext = (index, value) => {
if (value && index < 5) {
refs.current[index + 1].focus();
}
};
const focusPrevious = (index, key) => {
if (key === 'Backspace' && index > 0 && !code[index]) {
refs.current[index - 1].focus();
}
};
const handleCodeChange = (text, index) => {
const newCode = [...code];
newCode[index] = text;
setCode(newCode);
focusNext(index, text);
};
const handleSubmit = () => {
const fullCode = code.join('');
if (fullCode.length === 5) {
Keyboard.dismiss();
// 这里处理验证逻辑
console.log('验证码:', fullCode);
} else {
// 抖动动画效果
Animated.sequence([
Animated.timing(shakeAnim, {
toValue: 10,
duration: 50,
useNativeDriver: true
}),
Animated.timing(shakeAnim, {
toValue: -10,
duration: 50,
useNativeDriver: true
}),
Animated.timing(shakeAnim, {
toValue: 10,
duration: 50,
useNativeDriver: true
}),
Animated.timing(shakeAnim, {
toValue: 0,
duration: 50,
useNativeDriver: true
})
]).start();
}
};
const handleClear = () => {
setCode(['', '', '', '', '']);
refs.current[0].focus();
};
return (
<View className="w-full mt-8">
<Animated.View
style={{
transform: [{ translateX: shakeAnim }]
}}
className="flex flex-row justify-center space-x-3 mb-6 gap-[1rem]"
>
{code.map((digit, index) => (
<TextInput
key={index}
ref={ref => refs.current[index] = ref}
className="w-16 h-16 bg-[#FFF8DE] rounded-xl text-textTertiary text-3xl text-center"
keyboardType="number-pad"
maxLength={1}
value={digit}
onChangeText={text => handleCodeChange(text, index)}
onKeyPress={({ nativeEvent: { key } }) => focusPrevious(index, key)}
selectTextOnFocus
caretHidden={true}
/>
))}
</Animated.View>
<View className="flex-row justify-center space-x-4">
<TouchableOpacity
onPress={handleClear}
className="px-6 py-3 border border-purple-400 rounded-full"
>
<Text className="text-purple-300 font-medium"></Text>
</TouchableOpacity>
<TouchableOpacity
onPress={handleSubmit}
className="bg-amber-400 px-8 py-3 rounded-full shadow"
activeOpacity={0.8}
>
<Text className="text-purple-900 font-bold"></Text>
</TouchableOpacity>
</View>
<View className="mt-6 flex-row justify-center space-x-2">
<Text className="text-purple-300">?</Text>
<TouchableOpacity>
<Text className="text-amber-400 font-medium"></Text>
</TouchableOpacity>
</View>
</View>
);
};
export default VerificationCodeInput;