|
1 | | -import React, { useEffect, useRef } from 'react'; |
| 1 | +import React, { useEffect, useRef, useState } from 'react'; |
2 | 2 | import { |
3 | 3 | View, |
4 | 4 | Text, |
5 | 5 | Animated, |
6 | 6 | TouchableOpacity, |
7 | 7 | Easing, |
8 | 8 | SafeAreaView, |
| 9 | + LayoutChangeEvent, |
9 | 10 | } from 'react-native'; |
10 | 11 | import { main_colors } from '../assets/TabColor'; |
11 | 12 | import { ColorfulStyle } from '../assets/TabStyle'; |
@@ -49,6 +50,8 @@ const ColorfulTabBar = ({ |
49 | 50 | > |
50 | 51 | {state.routes.map((route, index) => { |
51 | 52 | const focusAnimation = useRef(new Animated.Value(0)).current; |
| 53 | + const [width_text, setWidthText] = useState(0) |
| 54 | + const [width_icon, setWidthIcon] = useState(0) |
52 | 55 |
|
53 | 56 | const { options } = descriptors[route.key]; |
54 | 57 | const label = |
@@ -166,9 +169,17 @@ const ColorfulTabBar = ({ |
166 | 169 | })`, |
167 | 170 | ], |
168 | 171 | }); |
169 | | - const marginLeftText = focusAnimation.interpolate({ |
| 172 | + |
| 173 | + const HALF_ICON_WIDTH = width_icon/2 |
| 174 | + const TEXT_ICON_WIDTH = width_text+HALF_ICON_WIDTH |
| 175 | + |
| 176 | + const translateXIcon = focusAnimation.interpolate({ |
170 | 177 | inputRange: [0, 1], |
171 | | - outputRange: [-50, 7], |
| 178 | + outputRange: [0, -(TEXT_ICON_WIDTH)/2], |
| 179 | + }); |
| 180 | + const translateXText = focusAnimation.interpolate({ |
| 181 | + inputRange: [0, 1], |
| 182 | + outputRange: [0, (HALF_ICON_WIDTH)+5], |
172 | 183 | }); |
173 | 184 | const opacityText = focusAnimation.interpolate({ |
174 | 185 | inputRange: [0.3, 1], |
@@ -202,22 +213,40 @@ const ColorfulTabBar = ({ |
202 | 213 | }, |
203 | 214 | ]} |
204 | 215 | > |
205 | | - <View>{renderIcon(isFocused)}</View> |
| 216 | + <Animated.View style={{ |
| 217 | + position: 'absolute', |
| 218 | + transform: [ |
| 219 | + {translateX: translateXIcon} |
| 220 | + ] |
| 221 | + }} |
| 222 | + onLayout={(e: LayoutChangeEvent) => { |
| 223 | + const {width} = e.nativeEvent.layout |
| 224 | + setWidthIcon(width) |
| 225 | + }}> |
| 226 | + {renderIcon(isFocused)} |
| 227 | + </Animated.View> |
206 | 228 |
|
207 | 229 | <Animated.View |
208 | 230 | style={{ |
209 | | - marginLeft: marginLeftText, |
| 231 | + position: 'absolute', |
210 | 232 | opacity: opacityText, |
| 233 | + transform: [ |
| 234 | + {translateX: translateXText} |
| 235 | + ], |
| 236 | + }} |
| 237 | + onLayout={(e: LayoutChangeEvent) => { |
| 238 | + const {width} = e.nativeEvent.layout |
| 239 | + setWidthText(width) |
211 | 240 | }} |
212 | 241 | > |
213 | 242 | <Text |
214 | 243 | numberOfLines={1} |
215 | 244 | style={[ |
216 | 245 | ColorfulStyle.itemText, |
217 | | - labelStyle, |
218 | 246 | { |
219 | 247 | color: darkMode ? FOREGROUND_COLOR : color, |
220 | 248 | }, |
| 249 | + labelStyle, |
221 | 250 | ]} |
222 | 251 | > |
223 | 252 | {label} |
|
0 commit comments