Files
digital-pilates/components/NumberKeyboard.tsx

147 lines
3.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Ionicons } from '@expo/vector-icons';
import React from 'react';
import {
Dimensions,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
interface NumberKeyboardProps {
onNumberPress: (number: string) => void;
onDeletePress: () => void;
onDecimalPress: () => void;
hasDecimal?: boolean;
maxLength?: number;
currentValue?: string;
}
const { width } = Dimensions.get('window');
const keyWidth = (width - 80) / 3; // 减去左右边距和间隙
export default function NumberKeyboard({
onNumberPress,
onDeletePress,
onDecimalPress,
hasDecimal = false,
maxLength = 6,
currentValue = '',
}: NumberKeyboardProps) {
const handleNumberPress = (number: string) => {
if (currentValue.length >= maxLength) return;
// 防止输入多个0开头
if (currentValue === '0' && number === '0') return;
// 如果当前是0输入非0数字时替换
if (currentValue === '0' && number !== '0') {
// 这里不需要replace直接传递number即可
return;
}
onNumberPress(number);
};
const handleDecimalPress = () => {
if (hasDecimal || currentValue.includes('.')) return;
onDecimalPress();
};
const renderKey = (
value: string,
onPress: () => void,
style?: any,
textStyle?: any,
disabled?: boolean
) => (
<TouchableOpacity
style={[
styles.key,
{ width: keyWidth },
style,
disabled && styles.keyDisabled
]}
onPress={onPress}
disabled={disabled}
activeOpacity={0.7}
>
{value === 'delete' ? (
<Ionicons name="backspace-outline" size={24} color="#374151" />
) : (
<Text style={[styles.keyText, textStyle, disabled && styles.keyTextDisabled]}>
{value}
</Text>
)}
</TouchableOpacity>
);
return (
<View style={styles.container}>
<View style={styles.row}>
{renderKey('1', () => handleNumberPress('1'))}
{renderKey('2', () => handleNumberPress('2'))}
{renderKey('3', () => handleNumberPress('3'))}
</View>
<View style={styles.row}>
{renderKey('4', () => handleNumberPress('4'))}
{renderKey('5', () => handleNumberPress('5'))}
{renderKey('6', () => handleNumberPress('6'))}
</View>
<View style={styles.row}>
{renderKey('7', () => handleNumberPress('7'))}
{renderKey('8', () => handleNumberPress('8'))}
{renderKey('9', () => handleNumberPress('9'))}
</View>
<View style={styles.row}>
{renderKey(
'.',
handleDecimalPress,
undefined,
undefined,
hasDecimal || currentValue.includes('.')
)}
{renderKey('0', () => handleNumberPress('0'))}
{renderKey('delete', onDeletePress)}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#F9FAFB',
paddingVertical: 20,
paddingHorizontal: 20,
borderTopWidth: 1,
borderTopColor: '#E5E7EB',
},
row: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 12,
},
key: {
height: 50,
backgroundColor: '#FFFFFF',
borderRadius: 12,
alignItems: 'center',
justifyContent: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.05,
shadowRadius: 2,
elevation: 1,
borderWidth: 1,
borderColor: '#E5E7EB',
},
keyDisabled: {
backgroundColor: '#F3F4F6',
opacity: 0.5,
},
keyText: {
fontSize: 20,
fontWeight: '600',
color: '#374151',
},
keyTextDisabled: {
color: '#9CA3AF',
},
});