Untitled
unknown
plain_text
a year ago
3.8 kB
4
Indexable
import { ThemedText } from '@/components/ThemedText' import { ThemedView } from '@/components/ThemedView' import React, { FC, useState } from 'react' import { FlatList, NativeScrollEvent, NativeSyntheticEvent, StyleSheet, View } from 'react-native' import { SharedValue, useSharedValue } from 'react-native-reanimated' const hoursArray = Array.from({ length: 12 }, (_, i) => (i + 1).toString().padStart(2, '0')) const minutesArray = Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0')) const ranges = [['AM', 'PM'], hoursArray, minutesArray] const ITEM_HEIGHT = 60 type ListComponentProps = { item: string index: number contentOffset: SharedValue<number> } const ListComponent: FC<ListComponentProps> = ({ item, index, contentOffset }) => { // const animatedStyle = useAnimatedStyle(() => ({ // opacity: interpolate( // contentOffset.value, // [index * ITEM_HEIGHT - ITEM_HEIGHT, index * ITEM_HEIGHT, index * ITEM_HEIGHT + ITEM_HEIGHT], // [0.25, 1, 0.25], // 'clamp' // ), // })) return ( <View style={[ styles.viewText, { height: ITEM_HEIGHT, opacity: contentOffset.value === index * ITEM_HEIGHT ? 1 : 0.25 }, ]} > <ThemedText style={styles.text}>{item}</ThemedText> </View> ) } const Time = () => { // const [output, setOutput] = useState({ hours: '00', minutes: '00', ampm: 'AM', }) function handleChange(e: NativeSyntheticEvent<NativeScrollEvent>, rangeIndex: number) { const value = e.nativeEvent.contentOffset.y const itemIndex = Math.round(value / ITEM_HEIGHT) if (rangeIndex === 0) { setOutput(prev => ({ ...prev, ampm: ranges[rangeIndex][itemIndex] })) } else if (rangeIndex === 1) { setOutput(prev => ({ ...prev, hours: ranges[rangeIndex][itemIndex] })) } else { setOutput(prev => ({ ...prev, minutes: ranges[rangeIndex][itemIndex] })) } } return ( <ThemedView style={styles.container}> <View style={[ styles.verticalSplitter, { height: ITEM_HEIGHT * 3, // 5 items rendered, just to have a longer scroll area }, ]} > {ranges.map((range, rangeIndex) => { const paddingVertical = ITEM_HEIGHT const contentOffset = useSharedValue(0) return ( <FlatList key={rangeIndex} data={range} contentContainerStyle={{ alignItems: 'center', paddingVertical, }} keyExtractor={(item, idx) => rangeIndex + idx + item} renderItem={props => <ListComponent {...props} contentOffset={contentOffset} />} snapToInterval={ITEM_HEIGHT} decelerationRate={'fast'} overScrollMode='never' bounces={false} scrollEventThrottle={16} onScroll={e => { contentOffset.value = e.nativeEvent.contentOffset.y }} showsVerticalScrollIndicator={false} onScrollEndDrag={e => handleChange(e, rangeIndex)} onMomentumScrollEnd={e => handleChange(e, rangeIndex)} /> ) })} </View> <ThemedText>{`Output: ${output.hours} ${output.minutes} ${output.ampm}`}</ThemedText> </ThemedView> ) } export default Time const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, verticalSplitter: { width: '100%', flexDirection: 'row', justifyContent: 'space-evenly', }, viewText: { justifyContent: 'center', alignItems: 'center', }, text: { fontSize: 48, lineHeight: 48, fontWeight: '700', }, })
Editor is loading...
Leave a Comment