我正在使用此自定义动画组件来响应本机导航底部的Tab。但是在单击选项卡时,导航部分可以正常工作,但是动画根本不会触发。
在控制台上登录statictabbar.js时,value和values变量都在更改,但在Tabbar.js中,它们不在控制台中登录。 关于从中删除onPress2功能
<TouchableWithoutFeedback onPress={() => {onPress(key); onPress2();}}>
动画正常运行
Tabbar.js
import React,{useState} 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 Navbar from '../components/Navbar'
import StaticTabbar from "../components/StaticTabbar";
const AnimatedSvg = Animated.createAnimatedComponent(Svg);
const { width } = Dimensions.get("window");
const height = 64;
// const { Path } = Svg;
const tabs = [
{
name: "grid",
},
{
name: "list",
},
{
name: "repeat",
},
{
name: "map",
},
{
name: "user",
},
];
const tabWidth = width / tabs.length;
const backgroundColor = "#fcce4e";
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
const Tabbar = ({ state, descriptors, navigation })=> {
const [value] = useState(new Animated.Value(0));
value.addListener(({value}) => console.log('line63 '+value))
// const { value } = this;
// console.log(value)
const translateX = value.interpolate({
inputRange: [0, width],
outputRange: [-width, 0],
});
translateX.addListener(({value}) => console.log('line63 '+value))
return (
<>
<View {...{ height, width }}>
<AnimatedSvg width={width * 2} {...{ height }} style={{ transform: [{ translateX }] }}>
<Path fill={backgroundColor} {...{ d }} />
</AnimatedSvg>
<View style={StyleSheet.absoluteFill}>
<StaticTabbar {...{ tabs, value, state, descriptors, navigation }} />
</View>
</View>
<SafeAreaView style={styles.container} />
</>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor,
},
});
export default Tabbar
StaticTabbar.js
import React,{useContext,useEffect,useMemo,useState} from "react";
import {
View, StyleSheet, TouchableWithoutFeedback, Animated, Dimensions,
} from "react-native";
import { Feather as Icon } from "@expo/vector-icons";
// import {BottomContext} from './Context'
const { width } = Dimensions.get("window");
const StaticTabbar = (props)=> {
const { tabs ,value, state, descriptors, navigation } = props;
// const [bottom,setBottom] = useContext(BottomContext);
useMemo(()=>{
console.log('static')
},[value])
// console.log(value)
const values = tabs.map((tab, index) => new Animated.Value(index === 0 ? 1 : 0));
const onPress = (index) => {
// setBottom(index);
console.log('line22'+ index)
const tabWidth = width / tabs.length;
Animated.sequence([
Animated.parallel(
values.map(v => {console.log('bb');Animated.timing(v, {
toValue: 0,
duration: 100,
useNativeDriver: true,
});}),
),
Animated.parallel([
Animated.spring(value, {
toValue: tabWidth * index,
useNativeDriver: true,
}),
Animated.spring(values[index], {
toValue: 1,
useNativeDriver: true,
}),
]),
Animated.parallel(values.map(v=>{console.log('aa');}))
]).start();
}
// const { onPress } = this;
// const { tabs, value } = this.props;
return (
<View style={styles.container}>
{
state.routes.map((route, key) => {
// console.log(tabs[key].name)
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 = values[key].interpolate({
inputRange: [0, 1],
outputRange: [64, 0],
extrapolate: "clamp",
});
const opacity1 = values[key].interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: "clamp",
});
const { options } = descriptors[route.key];
const isFocused = state.key === key;
const onPress2 = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};
return (
<React.Fragment {...{ key }}>
<TouchableWithoutFeedback onPress={() => {onPress(key); onPress2();}}onLongPress={onLongPress} accessibilityRole="button"
accessibilityStates={isFocused ? ['selected'] : []}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}>
<Animated.View style={[styles.tab, { opacity }]}>
<Icon name={tabs[key].name} color="black" size={25} />
</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={tabs[key].name} color="black" size={25} />
</View>
</Animated.View>
</React.Fragment>
);
})
}
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
},
tab: {
flex: 1,
justifyContent: "center",
alignItems: "center",
height: 64,
},
activeIcon: {
backgroundColor: "#fcce4e",
width: 40,
height: 40,
borderRadius: 20,
justifyContent: "center",
alignItems: "center",
},
});
export default StaticTabbar