55'use strict' ;
66
77import * as React from 'react' ;
8- import { StyleSheet , View } from 'react-native' ;
8+ import { Animated , Easing , StyleSheet , View } from 'react-native' ;
99import { SegmentedControlTab } from './SegmentedControlTab' ;
1010
1111import type { SegmentedControlProps } from './types' ;
@@ -27,6 +27,9 @@ const SegmentedControl = ({
2727 backgroundColor,
2828 fontSize,
2929} : SegmentedControlProps ) => {
30+ const [ segmentWidth , setSegmentWidth ] = React . useState ( 0 ) ;
31+ const animation = React . useRef ( new Animated . Value ( 0 ) ) . current ;
32+
3033 const handleChange = ( index : number ) => {
3134 // mocks iOS's nativeEvent
3235 const event : any = {
@@ -38,14 +41,49 @@ const SegmentedControl = ({
3841 onChange && onChange ( event ) ;
3942 onValueChange && onValueChange ( values [ index ] ) ;
4043 } ;
44+
45+ React . useEffect ( ( ) => {
46+ if ( animation && segmentWidth ) {
47+ Animated . timing ( animation , {
48+ toValue : segmentWidth * ( selectedIndex || 0 ) ,
49+ duration : 300 ,
50+ easing : Easing . out ( Easing . quad ) ,
51+ useNativeDriver : true ,
52+ } ) . start ( ) ;
53+ }
54+ } , [ animation , segmentWidth , selectedIndex ] ) ;
55+
4156 return (
4257 < View
4358 style = { [
4459 styles . default ,
4560 style ,
4661 backgroundColor && { backgroundColor} ,
4762 ! enabled && styles . disabled ,
48- ] } >
63+ ] }
64+ onLayout = { ( {
65+ nativeEvent : {
66+ layout : { width} ,
67+ } ,
68+ } ) => {
69+ const newSegmentWidth = values . length ? width / values . length : 0 ;
70+ if ( newSegmentWidth !== segmentWidth ) {
71+ animation . setValue ( newSegmentWidth * ( selectedIndex || 0 ) ) ;
72+ setSegmentWidth ( newSegmentWidth ) ;
73+ }
74+ } } >
75+ { selectedIndex != null && segmentWidth ? (
76+ < Animated . View
77+ style = { [
78+ styles . slider ,
79+ {
80+ transform : [ { translateX : animation } ] ,
81+ width : segmentWidth ,
82+ backgroundColor : tintColor || 'white' ,
83+ } ,
84+ ] }
85+ />
86+ ) : null }
4987 { values &&
5088 values . map ( ( value , index ) => {
5189 return (
@@ -70,6 +108,8 @@ const SegmentedControl = ({
70108
71109const styles = StyleSheet . create ( {
72110 default : {
111+ overflow : 'hidden' ,
112+ position : 'relative' ,
73113 flexDirection : 'row' ,
74114 justifyContent : 'space-evenly' ,
75115 alignContent : 'center' ,
@@ -80,6 +120,12 @@ const styles = StyleSheet.create({
80120 disabled : {
81121 opacity : 0.4 ,
82122 } ,
123+ slider : {
124+ position : 'absolute' ,
125+ left : 0 ,
126+ height : '100%' ,
127+ borderRadius : 5 ,
128+ } ,
83129} ) ;
84130
85131export default SegmentedControl ;
0 commit comments