1 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
2 |
|
3 | import * as React from 'react';
|
4 | import { Animated, Easing, StyleSheet, I18nManager, Platform } from 'react-native';
|
5 | export default class TabBarIndicator extends React.Component {
|
6 | constructor(...args) {
|
7 | super(...args);
|
8 |
|
9 | _defineProperty(this, "fadeInIndicator", () => {
|
10 | const {
|
11 | navigationState,
|
12 | layout,
|
13 | width,
|
14 | getTabWidth
|
15 | } = this.props;
|
16 |
|
17 | if (!this.isIndicatorShown && width === 'auto' && layout.width &&
|
18 | navigationState.routes.every((_, i) => getTabWidth(i))) {
|
19 | this.isIndicatorShown = true;
|
20 | Animated.timing(this.opacity, {
|
21 | toValue: 1,
|
22 | duration: 150,
|
23 | easing: Easing.in(Easing.linear),
|
24 | useNativeDriver: true
|
25 | }).start();
|
26 | }
|
27 | });
|
28 |
|
29 | _defineProperty(this, "isIndicatorShown", false);
|
30 |
|
31 | _defineProperty(this, "opacity", new Animated.Value(this.props.width === 'auto' ? 0 : 1));
|
32 |
|
33 | _defineProperty(this, "getTranslateX", (position, routes, getTabWidth) => {
|
34 | const inputRange = routes.map((_, i) => i);
|
35 |
|
36 | const outputRange = routes.reduce((acc, _, i) => {
|
37 | if (i === 0) return [0];
|
38 | return [...acc, acc[i - 1] + getTabWidth(i - 1)];
|
39 | }, []);
|
40 | const translateX = position.interpolate({
|
41 | inputRange,
|
42 | outputRange,
|
43 | extrapolate: 'clamp'
|
44 | });
|
45 | return Animated.multiply(translateX, I18nManager.isRTL ? -1 : 1);
|
46 | });
|
47 | }
|
48 |
|
49 | componentDidMount() {
|
50 | this.fadeInIndicator();
|
51 | }
|
52 |
|
53 | componentDidUpdate() {
|
54 | this.fadeInIndicator();
|
55 | }
|
56 |
|
57 | render() {
|
58 | const {
|
59 | position,
|
60 | navigationState,
|
61 | getTabWidth,
|
62 | width,
|
63 | style,
|
64 | layout
|
65 | } = this.props;
|
66 | const {
|
67 | routes
|
68 | } = navigationState;
|
69 | const transform = [];
|
70 |
|
71 | if (layout.width) {
|
72 | const translateX = routes.length > 1 ? this.getTranslateX(position, routes, getTabWidth) : 0;
|
73 | transform.push({
|
74 | translateX
|
75 | });
|
76 | }
|
77 |
|
78 | if (width === 'auto') {
|
79 | const inputRange = routes.map((_, i) => i);
|
80 | const outputRange = inputRange.map(getTabWidth);
|
81 | transform.push({
|
82 | scaleX: routes.length > 1 ? position.interpolate({
|
83 | inputRange,
|
84 | outputRange,
|
85 | extrapolate: 'clamp'
|
86 | }) : outputRange[0]
|
87 | }, {
|
88 | translateX: 0.5
|
89 | });
|
90 | }
|
91 |
|
92 | return React.createElement(Animated.View, {
|
93 | style: [styles.indicator, {
|
94 | width: width === 'auto' ? 1 : width
|
95 | },
|
96 |
|
97 |
|
98 |
|
99 | layout.width && Platform.OS !== 'macos' ? {
|
100 | left: 0
|
101 | } : {
|
102 | left: `${100 / routes.length * navigationState.index}%`
|
103 | }, {
|
104 | transform
|
105 | }, width === 'auto' ? {
|
106 | opacity: this.opacity
|
107 | } : null, style]
|
108 | });
|
109 | }
|
110 |
|
111 | }
|
112 | const styles = StyleSheet.create({
|
113 | indicator: {
|
114 | backgroundColor: '#ffeb3b',
|
115 | position: 'absolute',
|
116 | left: 0,
|
117 | bottom: 0,
|
118 | right: 0,
|
119 | height: 2
|
120 | }
|
121 | });
|
122 |
|
\ | No newline at end of file |