Настройки среды: Запуск USB на устройстве Samsung S6 android. Убунту 18.04. Chrome Отладка отключена.
"dependencies": {
"@react-native-community/masked-view": "^0.1.6",
"d3": "^5.15.0",
"jetifier": "^1.6.5",
"moment": "^2.24.0",
"react": "^16.12.0",
"react-native": "0.61.5",
"react-native-gesture-handler": "^1.6.0",
"react-native-gifted-chat": "^0.13.0",
"react-native-reanimated": "^1.7.0",
"react-native-rename": "^2.4.1",
"react-native-router-flux": "^4.2.0",
"react-native-safe-area-context": "^0.7.3",
"react-native-screens": "^2.0.0",
"react-native-shadow": "^1.2.2",
"react-native-svg": "^11.0.1",
"react-native-vector-icons": "^6.6.0",
"react-with-direction": "^1.3.1"
},
TabBar еще не готов к работе, но пробовал без функции действий от router-flux, и это довольно быстро. примерно в 2 или 3 раза быстрее, чем когда вызывается действие. Это традиционный компонент. Может быть, вызов render может вызвать рендеринг с каждой вкладки всего, что пульсирует при нажатии? Я попытался изменить if if в actionExecute () внутри StaticTabbar. js, но ничего не изменилось с точки зрения производительности. Я также хотел бы отметить, что весь этот контент имеет статус c и не вызывается ни один сетевой запрос, и я не использую expo.
StaticTabbar. js Компонент
import * as React from "react";
import {
View,
Text,
Animated,
Dimensions,
StyleSheet,
TouchableWithoutFeedback
} from "react-native";
import { Actions } from "react-native-router-flux";
import Icon from 'react-native-vector-icons/Feather';
const { width } = Dimensions.get("window");
export default class StaticTabbar extends React.PureComponent {
constructor(props) {
super(props);
const { tabs } = this.props;
this.values = tabs.map((tab, index) => new Animated.Value(index === 0 ? 1 : 0));
};
onPress = index => {
const { value, tabs } = this.props;
const tabWidth = width / tabs.length;
Animated.sequence([
Animated.parallel(
this.values.map(v => Animated.timing(v, {
toValue: 0,
duration: 100,
useNativeDriver: true,
})),
),
Animated.parallel([
Animated.spring(value, {
toValue: tabWidth * index,
useNativeDriver: true,
}),
Animated.spring(this.values[index], {
toValue: 1,
useNativeDriver: true,
}),
]),
]).start();
}
render() {
const { onPress } = this;
const { tabs, value } = this.props;
return (
<View style={styles.container}>
{
tabs.map((tab, key) => {
const actionExecute = () => {
if (tab.name === "Chats") {return Actions.chats()}
else if (tab.name === "Recents"){ return Actions.recents()}
else {return Actions.call()}
}
const tabWidth = width / tabs.length;
const cursor = tabWidth * key;
const opacity = value.interpolate({
inputRange: [cursor - tabWidth, cursor, cursor + tabWidth],
outputRange: [1, 0, 1],
extrapolate: "clamp",
});
const translateY = this.values[key].interpolate({
inputRange: [0, 1],
outputRange: [64, 0],
extrapolate: "clamp",
});
const opacity1 = this.values[key].interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: "clamp",
});
return (
<React.Fragment {...{ key }}>
<TouchableWithoutFeedback onPress={() => { onPress(key);actionExecute()}}>
<Animated.View style={[styles.tab, { opacity }]}>
<Icon name={tab.icon} size={18} style={{paddingRight:5}} color="#D8D1F3"/>
<Text style={{color: "rgba(255, 255, 255, 0.6)",fontSize: 15, fontFamily: "CerebriSans-Book"}}>
{tab.name}
</Text>
</Animated.View>
</TouchableWithoutFeedback>
<Animated.View style={{ position: "absolute", top: -8, left: tabWidth * key, width: tabWidth, height: 64, justifyContent: "center", alignItems: "center", opacity: opacity1, transform: [{ translateY }] }}>
<View style={styles.activeIcon}>
<Icon name={tab.icon} size={18} style={{paddingRight:5}} color="#3611BA"/>
<Text
style={{
color: "#3611BA",
fontSize: 15,
fontFamily: "CerebriSans-Bold",
}}
>{tab.name}</Text>
</View>
</Animated.View>
</React.Fragment>
);
})
}
</View>
);
};
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
},
tab: {
flexDirection: "row",
flex: 1,
justifyContent: "center",
alignItems: "center",
height: 60,
},
activeIcon: {
flexDirection: "row",
flex: 1,
backgroundColor: "transparent",
alignSelf: 'stretch',
height: 40,
justifyContent: "center",
alignItems: "center",
},
});
Tabbar . js
import * as React from "react";
import {
SafeAreaView, StyleSheet, Dimensions, View, Animated,
} from "react-native";
import * as shape from "d3-shape";
import Svg, {
Path
} from 'react-native-svg';
import StaticTabbar from "./StaticTabbar";
const AnimatedSvg = Animated.createAnimatedComponent(Svg);
const { width } = Dimensions.get("window");
const height = 60;
const tabs = [
{
name: "Chats",
icon: "message-circle"
},
{
name: "Recents",
icon: "arrow-down-left"
},
{
name: "Call",
icon: "phone-call"
},
];
const tabWidth = width / tabs.length;
const backgroundColor = "#360FC0";
const getPath = () => {
const left = shape.line().x(d => d.x).y(d => d.y)([
{ x: 0, y: 0 },
{ x: width, y: 0 },
]);
const tab = shape.line().x(d => d.x).y(d => d.y).curve(shape.curveBasis)([
{ x: width, y: 0 },
{ x: width + 5, y: 0 },
{ x: width + 10, y: 10 },
{ x: width + 15, y: height },
{ x: width + tabWidth - 15, y: height },
{ x: width + tabWidth - 10, y: 10 },
{ x: width + tabWidth - 5, y: 0 },
{ x: width + tabWidth, y: 0 },
]);
const right = shape.line().x(d => d.x).y(d => d.y)([
{ x: width + tabWidth, y: 0 },
{ x: width * 2, y: 0 },
{ x: width * 2, y: height },
{ x: 0, y: height },
{ x: 0, y: 0 },
]);
return `${left} ${tab} ${right}`;
};
const d = getPath();
// eslint-disable-next-line react/prefer-stateless-function
export default class Tabbar extends React.PureComponent {
value = new Animated.Value(0);
render() {
const { value } = this;
const translateX = value.interpolate({
inputRange: [0, width],
outputRange: [-width, 0],
});
return (
<>
<View {...{ height, width }}>
<AnimatedSvg width={width * 2} {...{ height }} style={{ transform: [{ translateX }] }}>
<Path fill={backgroundColor} {...{ d }} />
</AnimatedSvg>
<View style={StyleSheet.absoluteFill}>
<StaticTabbar {...{ tabs, value }} />
</View>
</View>
<SafeAreaView style={styles.container} />
</>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor,
},
});