131 lines
3.0 KiB
TypeScript
131 lines
3.0 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
StyleSheet,
|
|
Text,
|
|
TouchableOpacity,
|
|
View,
|
|
} from 'react-native';
|
|
import WheelPickerExpo from 'react-native-wheel-picker-expo';
|
|
|
|
export interface SelectionItem {
|
|
label: string;
|
|
value: string | number;
|
|
}
|
|
|
|
interface SlidingSelectionProps {
|
|
items: SelectionItem[];
|
|
selectedValue?: string | number;
|
|
onValueChange: (value: string | number, index: number) => void;
|
|
onConfirm?: (value: string | number, index: number) => void;
|
|
showConfirmButton?: boolean;
|
|
confirmButtonText?: string;
|
|
height?: number;
|
|
itemTextStyle?: any;
|
|
selectedIndicatorStyle?: any;
|
|
}
|
|
|
|
export function SlidingSelection({
|
|
items,
|
|
selectedValue,
|
|
onValueChange,
|
|
onConfirm,
|
|
showConfirmButton = true,
|
|
confirmButtonText = '确认',
|
|
height = 150,
|
|
itemTextStyle,
|
|
selectedIndicatorStyle
|
|
}: SlidingSelectionProps) {
|
|
const [currentIndex, setCurrentIndex] = useState(() => {
|
|
if (selectedValue !== undefined) {
|
|
const index = items.findIndex(item => item.value === selectedValue);
|
|
return index >= 0 ? index : 0;
|
|
}
|
|
return 0;
|
|
});
|
|
|
|
const handleValueChange = (index: number) => {
|
|
setCurrentIndex(index);
|
|
const selectedItem = items[index];
|
|
if (selectedItem) {
|
|
onValueChange(selectedItem.value, index);
|
|
}
|
|
};
|
|
|
|
const handleConfirm = () => {
|
|
const selectedItem = items[currentIndex];
|
|
if (selectedItem && onConfirm) {
|
|
onConfirm(selectedItem.value, currentIndex);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<View style={[styles.pickerContainer, { height }]}>
|
|
<WheelPickerExpo
|
|
height={height}
|
|
width={300}
|
|
initialSelectedIndex={currentIndex}
|
|
items={items.map(item => ({ label: item.label, value: item.value }))}
|
|
onChange={({ item, index }) => handleValueChange(index)}
|
|
backgroundColor="transparent"
|
|
haptics
|
|
/>
|
|
</View>
|
|
|
|
{showConfirmButton && (
|
|
<TouchableOpacity
|
|
style={styles.confirmButton}
|
|
onPress={handleConfirm}
|
|
activeOpacity={0.8}
|
|
>
|
|
<Text style={styles.confirmButtonText}>{confirmButtonText}</Text>
|
|
</TouchableOpacity>
|
|
)}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
alignItems: 'center',
|
|
width: '100%',
|
|
},
|
|
pickerContainer: {
|
|
width: '100%',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
picker: {
|
|
width: '100%',
|
|
height: '100%',
|
|
},
|
|
itemText: {
|
|
fontSize: 16,
|
|
color: '#333',
|
|
fontWeight: '500',
|
|
},
|
|
selectedIndicator: {
|
|
backgroundColor: 'rgba(74, 144, 226, 0.1)',
|
|
borderRadius: 8,
|
|
},
|
|
confirmButton: {
|
|
backgroundColor: '#4A90E2',
|
|
paddingHorizontal: 32,
|
|
paddingVertical: 12,
|
|
borderRadius: 20,
|
|
marginTop: 16,
|
|
shadowColor: '#000',
|
|
shadowOffset: {
|
|
width: 0,
|
|
height: 2,
|
|
},
|
|
shadowOpacity: 0.15,
|
|
shadowRadius: 4,
|
|
elevation: 4,
|
|
},
|
|
confirmButtonText: {
|
|
color: 'white',
|
|
fontSize: 16,
|
|
fontWeight: '600',
|
|
},
|
|
}); |