5
5
'use strict' ;
6
6
7
7
import * as React from 'react' ;
8
- import { StyleSheet , View } from 'react-native' ;
8
+ import { Animated , Easing , StyleSheet , View } from 'react-native' ;
9
9
import { SegmentedControlTab } from './SegmentedControlTab' ;
10
10
11
11
import type { SegmentedControlProps } from './types' ;
@@ -27,6 +27,9 @@ const SegmentedControl = ({
27
27
backgroundColor,
28
28
fontSize,
29
29
} : SegmentedControlProps ) => {
30
+ const [ segmentWidth , setSegmentWidth ] = React . useState ( 0 ) ;
31
+ const animation = React . useRef ( new Animated . Value ( 0 ) ) . current ;
32
+
30
33
const handleChange = ( index : number ) => {
31
34
// mocks iOS's nativeEvent
32
35
const event : any = {
@@ -38,14 +41,49 @@ const SegmentedControl = ({
38
41
onChange && onChange ( event ) ;
39
42
onValueChange && onValueChange ( values [ index ] ) ;
40
43
} ;
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
+
41
56
return (
42
57
< View
43
58
style = { [
44
59
styles . default ,
45
60
style ,
46
61
backgroundColor && { backgroundColor} ,
47
62
! 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 }
49
87
{ values &&
50
88
values . map ( ( value , index ) => {
51
89
return (
@@ -70,6 +108,8 @@ const SegmentedControl = ({
70
108
71
109
const styles = StyleSheet . create ( {
72
110
default : {
111
+ overflow : 'hidden' ,
112
+ position : 'relative' ,
73
113
flexDirection : 'row' ,
74
114
justifyContent : 'space-evenly' ,
75
115
alignContent : 'center' ,
@@ -80,6 +120,12 @@ const styles = StyleSheet.create({
80
120
disabled : {
81
121
opacity : 0.4 ,
82
122
} ,
123
+ slider : {
124
+ position : 'absolute' ,
125
+ left : 0 ,
126
+ height : '100%' ,
127
+ borderRadius : 5 ,
128
+ } ,
83
129
} ) ;
84
130
85
131
export default SegmentedControl ;
0 commit comments