@@ -6,13 +6,13 @@ import {
66 TextStyle ,
77 ViewStyle ,
88 LayoutChangeEvent ,
9- TouchableOpacity ,
109 Text ,
1110 ScrollView ,
1211 Animated ,
1312 NativeSyntheticEvent ,
1413 NativeScrollEvent ,
1514 Platform ,
15+ Pressable ,
1616} from 'react-native' ;
1717
1818export interface PickerDate {
@@ -58,18 +58,17 @@ const Picker = (props: PickerProps) => {
5858 value = 0 ,
5959 onChange,
6060 } = props ;
61+ const Y = useRef ( new Animated . Value ( 0 ) ) . current ;
6162 const scrollView = useRef < ScrollView > ( ) ;
6263 const ItemHeights = useRef < Array < number > > ( [ ] ) . current ;
63- const onPressORonScroll = useRef < 'onPress' | 'onScroll' > ( 'onScroll' ) ;
64- const timer = useRef < NodeJS . Timeout > ( ) ;
6564 const saveY = useRef < number > ( 0 ) ;
66- const Y = useRef ( new Animated . Value ( 0 ) ) . current ;
65+ const timer = useRef < NodeJS . Timeout > ( ) ;
66+ const onPressORonScroll = useRef < 'onPress' | 'onScroll' > ( 'onScroll' ) ;
6767 const currentY = useRef < number > ( 0 ) ;
68- const isTouchEnd = useRef < boolean > ( false ) ;
69- const isScroll = useRef < boolean > ( false ) ;
7068 const [ current , setCurrent ] = useState ( 0 ) ;
7169 useEffect ( ( ) => {
7270 onChange ?.( current ) ;
71+ onPressORonScroll . current = 'onScroll' ;
7372 } , [ current ] ) ;
7473 useEffect ( ( ) => {
7574 if ( value !== current ) {
@@ -93,93 +92,77 @@ const Picker = (props: PickerProps) => {
9392 containerHeight,
9493 } ;
9594 } , [ containerStyle , textStyle ] ) ;
95+ const getItemHeight = ( event : LayoutChangeEvent ) => {
96+ const { height } = event . nativeEvent . layout ;
97+ const round = Math . round ( height ) ;
98+ ItemHeights ?. push ( round * ItemHeights . length + round ) ;
99+ } ;
100+
96101 const location = ( scrollY : number , index : number ) => {
97- scrollView . current ?. scrollTo ( { x : 0 , y : scrollY - ( style . containerHeight as number ) , animated : true } ) ;
98102 saveY . current = scrollY - ( style . containerHeight as number ) ;
99103 currentY . current = index ;
100- if ( Platform . OS === 'android' ) {
101- setCurrent ( index ) ;
102- }
103- } ;
104- const scrollYEnd = ( event : NativeSyntheticEvent < NativeScrollEvent > ) => {
105- if ( onPressORonScroll . current === 'onScroll' ) {
106- return ;
107- }
108- const scrollY = event . nativeEvent . contentOffset . y ;
109- const currentHeight = ItemHeights [ currentY . current ] - ItemHeights [ 0 ] ;
110- if ( scrollY - 2 <= currentHeight && scrollY + 2 >= currentHeight ) {
111- setCurrent ( currentY . current ) ;
112- }
113- onPressORonScroll . current = 'onScroll' ;
104+ let an = Platform . OS === 'android' && { duration : 0 } ;
105+ let os = Platform . OS === 'ios' && { animated : false } ;
106+ scrollView . current ?. scrollTo ( { x : 0 , y : scrollY - ( style . containerHeight as number ) , ...an , ...os } ) ;
107+ setCurrent ( index ) ;
114108 } ;
115- const setScrollY = ( ) => {
116- if ( onPressORonScroll . current === 'onPress' ) {
117- return false ;
118- }
119- isTouchEnd . current = true ;
120- if ( ! isTouchEnd . current || ! isScroll . current ) {
121- return false ;
122- }
123- if ( saveY . current <= ItemHeights [ 0 ] / 1.1 ) {
109+ const setScrollHandle = ( val : number ) => {
110+ const spot = val / ItemHeights [ 0 ] ;
111+ if ( spot <= 0.6 ) {
124112 scrollView . current ?. scrollTo ( { x : 0 , y : 0 , animated : true } ) ;
125- saveY . current = 0 ;
126113 setCurrent ( 0 ) ;
127114 return false ;
128115 }
129- const spot = saveY . current / ItemHeights [ 0 ] + '' ;
130- const integer = Number ( spot . substr ( 0 , spot . indexOf ( '.' ) ) ) ;
131- const decimal = Number ( spot [ spot . indexOf ( '.' ) + 1 ] ) ;
132- const itemIndex = decimal >= 9 ? integer + 1 : integer ;
116+ const stringSpot = spot + '' ;
117+ const integer = Math . floor ( spot ) ;
118+ const decimal = Number ( stringSpot [ stringSpot . indexOf ( '.' ) + 1 ] ) ;
119+ const itemIndex = decimal >= 6 ? integer + 1 : integer ;
133120 scrollView . current ?. scrollTo ( { x : 0 , y : ItemHeights [ itemIndex ] - ItemHeights [ 0 ] , animated : true } ) ;
134- setCurrent ( itemIndex ) ;
135121 saveY . current = ItemHeights [ itemIndex ] - ItemHeights [ 0 ] ;
136- isScroll . current = false ;
137- isTouchEnd . current = false ;
122+ setCurrent ( itemIndex ) ;
123+ clearTimeout ( timer . current ! ) ;
124+ timer . current = undefined ;
138125 } ;
139- const getItemHeight = ( event : LayoutChangeEvent ) => {
140- const { height } = event . nativeEvent . layout ;
141- ItemHeights ?. push ( height * ItemHeights . length + height ) ;
126+ const listener = ( event : NativeSyntheticEvent < NativeScrollEvent > ) => {
127+ if ( onPressORonScroll . current === 'onPress' ) return ;
128+ saveY . current = event . nativeEvent . contentOffset . y ;
129+ if ( timer . current ) {
130+ clearTimeout ( timer . current ! ) ;
131+ timer . current = undefined ;
132+ }
133+ timer . current = setTimeout ( ( ) => {
134+ setScrollHandle ( saveY . current ) ;
135+ } , 160 ) ;
136+ } ;
137+ const onTouchEnd = ( ) => {
138+ if ( Platform . OS === 'ios' ) {
139+ if ( onPressORonScroll . current === 'onPress' ) {
140+ setCurrent ( currentY . current ) ;
141+ return ;
142+ }
143+ if ( timer . current ) return ;
144+ setScrollHandle ( saveY . current ) ;
145+ }
142146 } ;
143147 return (
144148 < View style = { { paddingVertical : 10 , height : ( style . containerHeight as number ) * lines + 10 } } >
145149 < ScrollView
146150 showsVerticalScrollIndicator = { false }
147- style = { { marginTop : - 1 } }
148151 ref = { scrollView as React . LegacyRef < ScrollView > }
149- onMomentumScrollEnd = { scrollYEnd }
150152 scrollEventThrottle = { 16 }
151- onTouchEnd = { setScrollY }
153+ onTouchEnd = { Platform . OS === 'ios' ? onTouchEnd : undefined }
152154 onScroll = { Animated . event ( [ { nativeEvent : { contentOffset : { y : Y } } } ] , {
153- listener : ( event : NativeSyntheticEvent < NativeScrollEvent > ) => {
154- const flag = Platform . OS === 'android' ? false : ! isTouchEnd . current ;
155- if ( onPressORonScroll . current === 'onPress' || flag ) {
156- return false ;
157- }
158- if ( saveY . current === event . nativeEvent . contentOffset . y ) {
159- return false ;
160- }
161- isScroll . current = false ;
162- saveY . current = event . nativeEvent . contentOffset . y ;
163- if ( timer . current ) {
164- clearTimeout ( timer . current ! ) ;
165- timer . current = undefined ;
166- }
167- timer . current = setTimeout ( ( ) => {
168- isScroll . current = true ;
169- setScrollY ( ) ;
170- clearTimeout ( timer . current ! ) ;
171- timer . current = undefined ;
172- } , 160 ) ;
173- } ,
155+ listener,
174156 useNativeDriver : false ,
175157 } ) }
176158 >
177159 { date . map ( ( item , index ) => (
178- < TouchableOpacity
160+ < Pressable
179161 onLayout = { getItemHeight }
180162 key = { index }
181- activeOpacity = { 1 }
163+ onPressOut = { Platform . OS === 'android' ? onTouchEnd : undefined }
182164 onPress = { ( ) => {
165+ if ( timer . current ) return ;
183166 onPressORonScroll . current = 'onPress' ;
184167 location ( ItemHeights ! [ index ] , index ) ;
185168 } }
@@ -191,12 +174,14 @@ const Picker = (props: PickerProps) => {
191174 < Text style = { current === index ? style . textAc : style . textUn } > { item [ key ] } </ Text >
192175 </ View >
193176 ) }
194- </ TouchableOpacity >
195- ) ) }
196- { new Array ( lines - 1 ) . fill ( '' ) . map ( ( item , index ) => (
197- < View key = { index } style = { style . containerUn } />
177+ </ Pressable >
198178 ) ) }
199- { /* style.containerHeight as number * lines + 10 */ }
179+ {
180+ < Pressable
181+ style = { [ style . containerUn , { height : ( style . containerHeight as number ) * ( lines - 1 ) } ] }
182+ onPressOut = { Platform . OS === 'android' ? onTouchEnd : undefined }
183+ />
184+ }
200185 </ ScrollView >
201186 < View style = { [ style . containerAc , { top : ( - style . containerHeight as number ) * lines + 10 } ] } />
202187 < View style = { [ style . containerAc , { top : ( - style . containerHeight as number ) * ( lines - 1 ) + 10 } ] } />
@@ -209,16 +194,22 @@ const styles = StyleSheet.create({
209194 height : 50 ,
210195 justifyContent : 'center' ,
211196 alignItems : 'center' ,
197+ paddingVertical : 0 ,
198+ paddingHorizontal : 0 ,
212199 } ,
213200 border : {
214201 backgroundColor : '#E6E6E6' ,
215202 height : 1 ,
216203 position : 'relative' ,
217204 zIndex : 999 ,
205+ paddingVertical : 0 ,
206+ paddingHorizontal : 0 ,
218207 } ,
219208 textStyle : {
220209 fontSize : 20 ,
221210 color : '#000' ,
211+ paddingVertical : 0 ,
212+ paddingHorizontal : 0 ,
222213 } ,
223214 acTextStyle : {
224215 color : '#fd8a00' ,
0 commit comments