11import React from 'react' ;
2- import { View , FlatList , Animated , Dimensions , PanResponder } from 'react-native' ;
2+ import { View , FlatList , Animated , Dimensions } from 'react-native' ;
3+ import { PanGestureHandler } from 'react-native-gesture-handler' ;
34
45const ScreenWidth = Dimensions . get ( 'window' ) . width ;
56
6- class FastScroll extends React . Component {
7+ class QuickScrollList extends React . Component {
78 constructor ( props ) {
89 super ( props ) ;
9- this . position = new Animated . ValueXY ( ) ;
10+ this . position = new Animated . Value ( 0 ) ;
11+ this . scrollBar = new Animated . Value ( ScreenWidth ) ;
1012 this . flatlistRef = React . createRef ( ) ;
11- this . panResponder = PanResponder . create ( {
12- onStartShouldSetPanResponder : ( ) => true ,
13- onMoveShouldSetPanResponder : ( ) => true ,
14- onPanResponderMove : ( event , gesture ) => {
15- const { thumbHeight, viewportHeight } = this . props ;
16- const positionY = this . position . __getValue ( ) . y ;
17- const availHeight = viewportHeight - thumbHeight ;
18- if ( positionY >= 0 && positionY <= availHeight ) {
19- this . onThumbDrag ( event , gesture ) ;
20- } else if ( gesture . moveY > 0 && gesture . moveY < availHeight ) {
21- this . onThumbDrag ( event , gesture ) ;
22- }
23- }
24- } ) ;
13+ this . disableOnScrollEvent = false ;
2514 }
2615
2716 static defaultProps = {
28- ref : ref => { } ,
29- onScroll : ( ) => { } ,
30- onScrollEndDrag : ( ) => { } ,
3117 flashDuration : 40 ,
32- flashOutDuration : 1500 ,
33- rightOffset : 15 ,
34- thumbHeight : 80 ,
35- hiddenPosition : ScreenWidth + 15 ,
18+ flashOutDuration : 2000 ,
19+ rightOffset : 12 ,
20+ thumbHeight : 60 ,
21+ hiddenPosition : ScreenWidth + 10 ,
3622 touchAreaWidth : 25 ,
3723 thumbStyle : { } ,
3824 scrollbarStyle : { } ,
3925 containerStyle : { }
4026 } ;
4127
42- state = { scrollBar : new Animated . Value ( ScreenWidth ) } ;
43-
4428 createRef = ref => {
4529 this . flatlistRef = ref ;
46- this . props . ref ( ref ) ;
30+ this . props . ref && this . props . ref ( ref ) ;
4731 } ;
4832
49- onThumbDrag ( event , gesture ) {
33+ onThumbDrag = event => {
5034 const { data, itemHeight, thumbHeight, viewportHeight } = this . props ;
51- // Animated.event([null, { dy: this.position.y }], { useNativeDriver: true })(event, gesture);
52- this . position . setValue ( { x : 0 , y : gesture . moveY } ) ;
53- const thumbOffset = this . position . __getValue ( ) . y ;
54- const lastIndex = Math . floor ( ( data . length * itemHeight - viewportHeight ) / itemHeight ) + 1 ;
55- const thumbPos = ( thumbOffset / ( viewportHeight - thumbHeight ) ) . toFixed ( 3 ) ;
56- let index = Math . floor ( lastIndex * thumbPos ) ;
57- if ( index > lastIndex ) index = lastIndex ;
58- if ( index < 0 ) index = 0 ;
59- this . flatlistRef . scrollToIndex ( {
60- index,
61- viewPosition : 0 ,
62- animated : true
63- } ) ;
64- }
35+ const availableHeight = viewportHeight - thumbHeight ;
36+ const positionY = this . position . __getValue ( ) ;
37+ const gestureY = event . nativeEvent . absoluteY ;
38+ if ( gestureY >= 0 && gestureY <= availableHeight ) {
39+ this . disableOnScrollEvent = true ;
40+ const thumbPos = ( positionY / ( viewportHeight - thumbHeight ) ) . toFixed ( 3 ) ;
41+ let lastIndex = data . length - Math . floor ( viewportHeight / itemHeight ) + 1 ;
42+ let index = Math . floor ( lastIndex * thumbPos ) ;
43+ if ( index > lastIndex ) index = lastIndex ;
44+ if ( index < 0 ) index = 0 ;
45+ Animated . event ( [ { nativeEvent : { absoluteY : this . position } } ] ) ( event ) ;
46+ this . flatlistRef . scrollToIndex ( {
47+ index,
48+ viewPosition : 0 ,
49+ animated : true
50+ } ) ;
51+ }
52+ } ;
6553
66- moveThumbOnScroll ( e ) {
54+ moveThumbOnScroll = e => {
55+ if ( this . disableOnScrollEvent ) {
56+ this . disableOnScrollEvent = false ;
57+ return ;
58+ }
6759 const { itemHeight, data, thumbHeight, viewportHeight } = this . props ;
6860 const listHeight = data . length * itemHeight ;
6961 const endPosition = listHeight - viewportHeight ;
7062 const offsetY = e . nativeEvent . contentOffset . y ;
7163 const diff = ( viewportHeight - thumbHeight ) / endPosition ;
72- this . position . setValue ( { x : 0 , y : offsetY * diff } ) ;
73- }
64+ this . position . setValue ( offsetY * diff ) ;
65+ } ;
7466
7567 flashScrollBar = ( ) => {
7668 const { flashDuration, rightOffset } = this . props ;
77- Animated . timing ( this . state . scrollBar , {
69+ Animated . timing ( this . scrollBar , {
7870 toValue : ScreenWidth - rightOffset ,
7971 duration : flashDuration ,
8072 useNativeDriver : true
@@ -84,18 +76,18 @@ class FastScroll extends React.Component {
8476 onScroll = ( event , gesture ) => {
8577 this . flashScrollBar ( ) ;
8678 this . moveThumbOnScroll ( event ) ;
87- this . props . onScroll ( event , gesture ) ;
79+ this . props . onScroll && this . props . onScroll ( event , gesture ) ;
8880 } ;
8981
9082 onScrollEnd = ( event , gesture ) => {
9183 const { flashDuration, flashOutDuration } = this . props ;
92- const flashOut = Animated . timing ( this . state . scrollBar , {
84+ const flashOut = Animated . timing ( this . scrollBar , {
9385 toValue : this . props . hiddenPosition ,
9486 duration : flashDuration ,
9587 useNativeDriver : true
9688 } ) ;
9789 setTimeout ( ( ) => flashOut . start ( ) , flashOutDuration ) ;
98- this . props . onScrollEndDrag ( event , gesture ) ;
90+ this . props . onScrollEndDrag && this . props . onScrollEndDrag ( event , gesture ) ;
9991 } ;
10092
10193 convertStyle ( prop ) {
@@ -109,25 +101,11 @@ class FastScroll extends React.Component {
109101 return prop ;
110102 }
111103
112- itemLayout = ( ) => {
113- const { itemHeight, getItemLayout } = this . props ;
114- return getItemLayout
115- ? getItemLayout
116- : ( data , index ) => {
117- return { length : itemHeight , offset : itemHeight * index , index } ;
118- } ;
119- } ;
120-
121104 render ( ) {
122105 //prettier-ignore
123106 const { thumbHeight, thumbStyle, scrollbarStyle, containerStyle, viewportHeight, touchAreaWidth } = this . props ;
124- const rightOffset = {
125- transform : [
126- {
127- translateX : this . state . scrollBar
128- }
129- ]
130- } ;
107+ const rightOffset = { transform : [ { translateX : this . scrollBar } ] } ;
108+ const thumbTransform = { transform : [ { translateY : this . position } ] } ;
131109 return (
132110 < View style = { [ styles . mainWrapper , this . convertStyle ( containerStyle ) ] } >
133111 < FlatList
@@ -137,7 +115,6 @@ class FastScroll extends React.Component {
137115 onScrollEndDrag = { this . onScrollEnd }
138116 showsVerticalScrollIndicator = { false }
139117 onScrollToIndexFailed = { ( ) => { } }
140- getItemLayout = { this . itemLayout ( ) }
141118 />
142119 < Animated . View
143120 style = { [
@@ -146,24 +123,26 @@ class FastScroll extends React.Component {
146123 { height : viewportHeight } ,
147124 this . convertStyle ( scrollbarStyle )
148125 ] } >
149- < Animated . View
150- style = { [
151- styles . touchArea ,
152- this . position . getLayout ( ) ,
153- { height : thumbHeight , width : touchAreaWidth }
154- ] }
155- { ...this . panResponder . panHandlers } >
126+ < PanGestureHandler
127+ onGestureEvent = { this . onThumbDrag }
128+ hitSlop = { { left : touchAreaWidth } }
129+ maxPointers = { 1 } >
156130 < Animated . View
157- style = { [ styles . thumb , { height : thumbHeight } , this . convertStyle ( thumbStyle ) ] }
131+ style = { [
132+ styles . thumb ,
133+ thumbTransform ,
134+ { height : thumbHeight } ,
135+ this . convertStyle ( thumbStyle )
136+ ] }
158137 />
159- </ Animated . View >
138+ </ PanGestureHandler >
160139 </ Animated . View >
161140 </ View >
162141 ) ;
163142 }
164143}
165144
166- export default FastScroll ;
145+ export default QuickScrollList ;
167146
168147const styles = {
169148 mainWrapper : {
@@ -175,14 +154,10 @@ const styles = {
175154 backgroundColor : 'transparent' ,
176155 alignItems : 'center'
177156 } ,
178- touchArea : {
179- backgroundColor : 'transparent' ,
180- alignItems : 'center'
181- } ,
182157 thumb : {
183- width : 6 ,
158+ width : 4 ,
184159 borderRadius : 4 ,
185160 backgroundColor : '#4C4C4C' ,
186161 elevation : 2
187162 }
188- } ;
163+ } ;
0 commit comments