@@ -8,7 +8,7 @@ import _ from 'lodash';
8
8
9
9
import TabBarContext from './TabBarContext' ;
10
10
import TabBarItem from './TabBarItem' ;
11
- import ReanimatedObject from './ReanimatedObject' ;
11
+ // import ReanimatedObject from './ReanimatedObject';
12
12
import { asBaseComponent , forwardRef } from '../../commons' ;
13
13
import View from '../../components/view' ;
14
14
import Text from '../../components/text' ;
@@ -17,7 +17,23 @@ import {Constants} from '../../helpers';
17
17
import { LogService } from '../../services' ;
18
18
19
19
const DEFAULT_HEIGHT = 48 ;
20
- const { Code, Clock, Value, add, sub, cond, eq, stopClock, startClock, clockRunning, timing, block, set} = Reanimated ;
20
+ const INDICATOR_INSET = Spacings . s4 ;
21
+ const {
22
+ Code,
23
+ Clock,
24
+ Value,
25
+ and,
26
+ eq,
27
+ neq,
28
+ cond,
29
+ stopClock,
30
+ startClock,
31
+ interpolate,
32
+ Extrapolate,
33
+ timing,
34
+ block,
35
+ set
36
+ } = Reanimated ;
21
37
22
38
/**
23
39
* @description : TabController's TabBar component
@@ -99,11 +115,12 @@ class TabBar extends PureComponent {
99
115
this . tabBar = React . createRef ( ) ;
100
116
101
117
this . _itemsWidths = _ . times ( itemsCount , ( ) => null ) ;
102
- this . _indicatorOffset = new ReanimatedObject ( { duration : 300 , easing : Easing . bezier ( 0.23 , 1 , 0.32 , 1 ) } ) ;
103
- this . _indicatorWidth = new ReanimatedObject ( { duration : 300 , easing : Easing . bezier ( 0.23 , 1 , 0.32 , 1 ) } ) ;
118
+ this . _indicatorOffset = new Value ( 0 ) ;
119
+ this . _indicatorWidth = new Value ( 0 ) ;
120
+
104
121
this . _indicatorTransitionStyle = {
105
- width : this . _indicatorWidth . value ,
106
- left : this . _indicatorOffset . value
122
+ width : this . _indicatorWidth ,
123
+ left : this . _indicatorOffset
107
124
} ;
108
125
109
126
this . state = {
@@ -161,9 +178,16 @@ class TabBar extends PureComponent {
161
178
this . _itemsWidths [ itemIndex ] = itemWidth ;
162
179
if ( ! _ . includes ( this . _itemsWidths , null ) ) {
163
180
const { selectedIndex} = this . context ;
164
- const itemsOffsets = _ . map ( this . _itemsWidths , ( w , index ) => _ . sum ( _ . take ( this . _itemsWidths , index ) ) ) ;
165
- this . setState ( { itemsWidths : this . _itemsWidths , itemsOffsets} ) ;
166
- this . tabBar . current . scrollTo ( { x : itemsOffsets [ selectedIndex ] , animated : false } ) ;
181
+ const itemsOffsets = _ . map ( this . _itemsWidths ,
182
+ ( w , index ) => INDICATOR_INSET + _ . sum ( _ . take ( this . _itemsWidths , index ) ) ) ;
183
+ const itemsWidths = _ . map ( this . _itemsWidths , width => width - INDICATOR_INSET * 2 ) ;
184
+
185
+ this . setState ( { itemsWidths, itemsOffsets} ) ;
186
+ const selectedItemOffset = itemsOffsets [ selectedIndex ] - INDICATOR_INSET ;
187
+
188
+ if ( selectedItemOffset + this . _itemsWidths [ selectedIndex ] > Constants . screenWidth ) {
189
+ this . tabBar . current . scrollTo ( { x : selectedItemOffset , animated : true } ) ;
190
+ }
167
191
}
168
192
} ;
169
193
@@ -173,35 +197,6 @@ class TabBar extends PureComponent {
173
197
}
174
198
} ;
175
199
176
- runTiming ( targetValue , prevValue , duration ) {
177
- const clock = new Clock ( ) ;
178
- const state = {
179
- finished : new Value ( 0 ) ,
180
- position : prevValue ,
181
- time : new Value ( 0 ) ,
182
- frameTime : new Value ( 0 )
183
- } ;
184
-
185
- const config = {
186
- duration,
187
- toValue : targetValue ,
188
- easing : Easing . bezier ( 0.23 , 1 , 0.32 , 1 )
189
- } ;
190
-
191
- return block ( [
192
- cond ( clockRunning ( clock ) , [ ] , [ startClock ( clock ) ] ) ,
193
- timing ( clock , state , config ) ,
194
- cond ( state . finished , [
195
- stopClock ( clock ) ,
196
- set ( state . finished , 0 ) ,
197
- set ( state . time , 0 ) ,
198
- set ( state . frameTime , 0 ) ,
199
- set ( prevValue , state . position )
200
- ] ) ,
201
- state . position
202
- ] ) ;
203
- }
204
-
205
200
renderSelectedIndicator ( ) {
206
201
const { itemsWidths} = this . state ;
207
202
const { indicatorStyle} = this . props ;
@@ -248,7 +243,6 @@ class TabBar extends PureComponent {
248
243
} ) ;
249
244
} else {
250
245
// TODO: Remove once props.children is deprecated
251
-
252
246
if ( this . tabBarItems ) {
253
247
return this . tabBarItems ;
254
248
}
@@ -273,10 +267,35 @@ class TabBar extends PureComponent {
273
267
}
274
268
}
275
269
270
+ renderCodeBlock = ( ) => {
271
+ const { carouselOffset, asCarousel} = this . context ;
272
+ const { itemsWidths, itemsOffsets} = this . state ;
273
+ const nodes = [ ] ;
274
+
275
+ if ( asCarousel ) {
276
+ nodes . push ( set ( this . _indicatorOffset ,
277
+ interpolate ( carouselOffset , {
278
+ inputRange : itemsOffsets . map ( ( value , index ) => index * Constants . screenWidth ) ,
279
+ outputRange : itemsOffsets ,
280
+ extrapolate : Extrapolate . CLAMP
281
+ } ) ) ,
282
+ set ( this . _indicatorWidth ,
283
+ interpolate ( carouselOffset , {
284
+ inputRange : itemsWidths . map ( ( value , index ) => index * Constants . screenWidth ) ,
285
+ outputRange : itemsWidths ,
286
+ extrapolate : Extrapolate . CLAMP
287
+ } ) ) ) ;
288
+ } else {
289
+ nodes . push ( set ( this . _indicatorOffset , runIndicatorTimer ( new Clock ( ) , this . context . currentPage , itemsOffsets ) ) ,
290
+ set ( this . _indicatorWidth , runIndicatorTimer ( new Clock ( ) , this . context . currentPage , itemsWidths ) ) ) ;
291
+ }
292
+
293
+ return block ( nodes ) ;
294
+ } ;
295
+
276
296
render ( ) {
277
- const { currentPage, carouselOffset, asCarousel} = this . context ;
278
297
const { height, enableShadow, containerStyle} = this . props ;
279
- const { itemsWidths, itemsOffsets , scrollEnabled} = this . state ;
298
+ const { itemsWidths, scrollEnabled} = this . state ;
280
299
return (
281
300
< View
282
301
style = { [ styles . container , enableShadow && styles . containerShadow , { width : this . containerWidth } , containerStyle ] }
@@ -293,48 +312,7 @@ class TabBar extends PureComponent {
293
312
< View style = { [ styles . tabBar , height && { height} ] } > { this . renderTabBarItems ( ) } </ View >
294
313
{ this . renderSelectedIndicator ( ) }
295
314
</ ScrollView >
296
- { ! _ . isUndefined ( itemsWidths ) && (
297
- < Code >
298
- { ( ) => {
299
- const indicatorInset = Spacings . s4 ;
300
-
301
- return block ( asCarousel && _ . size ( itemsWidths ) > 1
302
- /* Transition for carousel pages */
303
- ? [
304
- set ( this . _indicatorOffset . value ,
305
- Reanimated . interpolate ( carouselOffset , {
306
- inputRange : itemsOffsets . map ( ( offset , index ) => index * Constants . screenWidth ) ,
307
- outputRange : itemsOffsets . map ( offset => offset + indicatorInset )
308
- } ) ) ,
309
- set ( this . _indicatorWidth . value ,
310
- Reanimated . interpolate ( carouselOffset , {
311
- inputRange : itemsWidths . map ( ( width , index ) => index * Constants . screenWidth ) ,
312
- outputRange : itemsWidths . map ( ( width , index ) => width - 2 * indicatorInset )
313
- } ) )
314
- ]
315
- /* Default transition */
316
- : [
317
- // calc indicator current width
318
- ..._ . map ( itemsWidths , ( width , index ) => {
319
- return cond ( eq ( currentPage , index ) , [
320
- set ( this . _indicatorWidth . nextValue , sub ( itemsWidths [ index ] , indicatorInset * 2 ) )
321
- ] ) ;
322
- } ) ,
323
- // calc indicator current position
324
- ..._ . map ( itemsOffsets , ( offset , index ) => {
325
- return cond ( eq ( currentPage , index ) , [
326
- set ( this . _indicatorOffset . nextValue , add ( itemsOffsets [ index ] , indicatorInset ) )
327
- ] ) ;
328
- } ) ,
329
-
330
- // Offset transition
331
- this . _indicatorOffset . getTransitionBlock ( ) ,
332
- // Width transition
333
- this . _indicatorWidth . getTransitionBlock ( )
334
- ] ) ;
335
- } }
336
- </ Code >
337
- ) }
315
+ { _ . size ( itemsWidths ) > 1 && < Code > { this . renderCodeBlock } </ Code > }
338
316
</ View >
339
317
) ;
340
318
}
@@ -386,4 +364,38 @@ const styles = StyleSheet.create({
386
364
}
387
365
} ) ;
388
366
367
+ function runIndicatorTimer ( clock , currentPage , values ) {
368
+ const state = {
369
+ finished : new Value ( 0 ) ,
370
+ position : new Value ( 0 ) ,
371
+ time : new Value ( 0 ) ,
372
+ frameTime : new Value ( 0 )
373
+ } ;
374
+
375
+ const config = {
376
+ duration : 300 ,
377
+ toValue : new Value ( 100 ) ,
378
+ easing : Easing . inOut ( Easing . ease )
379
+ } ;
380
+
381
+ return block ( [
382
+ ..._ . map ( values , ( value , index ) => {
383
+ return cond ( and ( eq ( currentPage , index ) , neq ( config . toValue , index ) ) , [
384
+ set ( state . finished , 0 ) ,
385
+ set ( state . time , 0 ) ,
386
+ set ( state . frameTime , 0 ) ,
387
+ set ( config . toValue , index ) ,
388
+ startClock ( clock )
389
+ ] ) ;
390
+ } ) ,
391
+ timing ( clock , state , config ) ,
392
+ cond ( state . finished , stopClock ( clock ) ) ,
393
+ interpolate ( state . position , {
394
+ inputRange : _ . times ( values . length ) ,
395
+ outputRange : values ,
396
+ extrapolate : Extrapolate . CLAMP
397
+ } )
398
+ ] ) ;
399
+ }
400
+
389
401
export default asBaseComponent ( forwardRef ( TabBar ) ) ;
0 commit comments