@@ -8,7 +8,7 @@ import _ from 'lodash';
88
99import TabBarContext from './TabBarContext' ;
1010import TabBarItem from './TabBarItem' ;
11- import ReanimatedObject from './ReanimatedObject' ;
11+ // import ReanimatedObject from './ReanimatedObject';
1212import { asBaseComponent , forwardRef } from '../../commons' ;
1313import View from '../../components/view' ;
1414import Text from '../../components/text' ;
@@ -17,7 +17,23 @@ import {Constants} from '../../helpers';
1717import { LogService } from '../../services' ;
1818
1919const 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 ;
2137
2238/**
2339 * @description : TabController's TabBar component
@@ -99,11 +115,12 @@ class TabBar extends PureComponent {
99115 this . tabBar = React . createRef ( ) ;
100116
101117 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+
104121 this . _indicatorTransitionStyle = {
105- width : this . _indicatorWidth . value ,
106- left : this . _indicatorOffset . value
122+ width : this . _indicatorWidth ,
123+ left : this . _indicatorOffset
107124 } ;
108125
109126 this . state = {
@@ -161,9 +178,16 @@ class TabBar extends PureComponent {
161178 this . _itemsWidths [ itemIndex ] = itemWidth ;
162179 if ( ! _ . includes ( this . _itemsWidths , null ) ) {
163180 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+ }
167191 }
168192 } ;
169193
@@ -173,35 +197,6 @@ class TabBar extends PureComponent {
173197 }
174198 } ;
175199
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-
205200 renderSelectedIndicator ( ) {
206201 const { itemsWidths} = this . state ;
207202 const { indicatorStyle} = this . props ;
@@ -248,7 +243,6 @@ class TabBar extends PureComponent {
248243 } ) ;
249244 } else {
250245 // TODO: Remove once props.children is deprecated
251-
252246 if ( this . tabBarItems ) {
253247 return this . tabBarItems ;
254248 }
@@ -273,10 +267,35 @@ class TabBar extends PureComponent {
273267 }
274268 }
275269
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+
276296 render ( ) {
277- const { currentPage, carouselOffset, asCarousel} = this . context ;
278297 const { height, enableShadow, containerStyle} = this . props ;
279- const { itemsWidths, itemsOffsets , scrollEnabled} = this . state ;
298+ const { itemsWidths, scrollEnabled} = this . state ;
280299 return (
281300 < View
282301 style = { [ styles . container , enableShadow && styles . containerShadow , { width : this . containerWidth } , containerStyle ] }
@@ -293,48 +312,7 @@ class TabBar extends PureComponent {
293312 < View style = { [ styles . tabBar , height && { height} ] } > { this . renderTabBarItems ( ) } </ View >
294313 { this . renderSelectedIndicator ( ) }
295314 </ 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 > }
338316 </ View >
339317 ) ;
340318 }
@@ -386,4 +364,38 @@ const styles = StyleSheet.create({
386364 }
387365} ) ;
388366
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+
389401export default asBaseComponent ( forwardRef ( TabBar ) ) ;
0 commit comments