动画在自定义React Native自定义底部导航中不起作用

时间:2020-09-01 14:56:04

标签: javascript node.js reactjs react-native react-native-navigation

我正在使用此自定义动画组件来响应本机导航底部的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

0 个答案:

没有答案