React Native【实战范例】弹跳动画菜单导航

最终效果

范例代码

c 复制代码
import React, { useEffect, useRef, useState } from "react";
import {
  Animated,
  Easing,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from "react-native";
export default function Demo() {
  const width1 = useRef(new Animated.Value(200)).current;
  const width2 = useRef(new Animated.Value(64)).current;
  const width3 = useRef(new Animated.Value(64)).current;
  const width4 = useRef(new Animated.Value(64)).current;
  const [index, setIndex] = useState(0);
  useEffect(() => {
    anim1(index === 0);
    anim2(index === 1);
    anim3(index === 2);
    anim4(index === 3);
  }, [index]);
  const anim1 = (isOpen) => {
    Animated.timing(width1, {
      toValue: isOpen ? 200 : 64,
      duration: isOpen ? 500 : 300,
      easing: isOpen ? Easing.elastic(3) : Easing.ease,
      useNativeDriver: false,
    }).start();
  };
  const anim2 = (isOpen) => {
    Animated.timing(width2, {
      toValue: isOpen ? 200 : 64,
      duration: isOpen ? 500 : 300,
      easing: isOpen ? Easing.elastic(3) : Easing.ease,
      useNativeDriver: false,
    }).start();
  };
  const anim3 = (isOpen) => {
    Animated.timing(width3, {
      toValue: isOpen ? 200 : 64,
      duration: isOpen ? 500 : 300,
      easing: isOpen ? Easing.elastic(3) : Easing.ease,
      useNativeDriver: false,
    }).start();
  };
  const anim4 = (isOpen) => {
    Animated.timing(width4, {
      toValue: isOpen ? 200 : 64,
      duration: isOpen ? 500 : 300,
      easing: isOpen ? Easing.elastic(3) : Easing.ease,
      useNativeDriver: false,
    }).start();
  };
  return (
    <View style={styles.root}>
      <TouchableOpacity
        activeOpacity={0.8}
        onPress={() => {
          setIndex(0);
        }}
      >
        <Animated.View
          style={[
            styles.view,
            { width: width1, opacity: index === 0 ? 1 : 0.75 },
          ]}
        >
          <Text style={styles.txt} numberOfLines={1} ellipsizeMode="clip">
            首页推荐
          </Text>
          <View style={styles.dot} />
        </Animated.View>
      </TouchableOpacity>
      <TouchableOpacity
        activeOpacity={0.8}
        onPress={() => {
          setIndex(1);
        }}
      >
        <Animated.View
          style={[
            styles.view,
            { width: width2, opacity: index === 1 ? 1 : 0.75 },
          ]}
        >
          <Text style={styles.txt} numberOfLines={1} ellipsizeMode="clip">
            热门直播
          </Text>
          <View style={styles.dot} />
        </Animated.View>
      </TouchableOpacity>
      <TouchableOpacity
        activeOpacity={0.8}
        onPress={() => {
          setIndex(2);
        }}
      >
        <Animated.View
          style={[
            styles.view,
            { width: width3, opacity: index === 2 ? 1 : 0.75 },
          ]}
        >
          <Text style={styles.txt} numberOfLines={1} ellipsizeMode="clip">
            我的礼物
          </Text>
          <View style={styles.dot} />
        </Animated.View>
      </TouchableOpacity>
      <TouchableOpacity
        activeOpacity={0.8}
        onPress={() => {
          setIndex(3);
        }}
      >
        <Animated.View
          style={[
            styles.view,
            { width: width4, opacity: index === 3 ? 1 : 0.75 },
          ]}
        >
          <Text style={styles.txt} numberOfLines={1} ellipsizeMode="clip">
            个人信息
          </Text>
          <View style={styles.dot} />
        </Animated.View>
      </TouchableOpacity>
    </View>
  );
}
const styles = StyleSheet.create({
  root: {
    width: "100%",
    height: "100%",
    backgroundColor: "white",
    flexDirection: "column",
    justifyContent: "center",
  },
  view: {
    height: 60,
    flexDirection: "row",
    alignItems: "center",
    marginVertical: 16,
    borderTopRightRadius: 28,
    borderBottomRightRadius: 28,
    backgroundColor: "#2030ff",
    paddingLeft: 16,
    overflow: "hidden",
  },
  img: {
    width: 32,
    height: 32,
    tintColor: "white",
  },
  txt: {
    fontSize: 18,
    color: "#ffffffD0",
    marginLeft: 16,
  },
  dot: {
    width: 10,
    height: 10,
    backgroundColor: "#20f020",
    marginLeft: 28,
    borderRadius: 5,
  },
});
相关推荐
结局无敌3 分钟前
React Native for OpenHarmony 实战:三方库 react-native-progress-steps 的鸿蒙化适配指南
javascript·人工智能·深度学习·react native·react.js·harmonyos
donk13142 天前
React Native for OpenHarmony 实战:三方库 react-native-circular-action-menu 的鸿蒙化适配指南
javascript·分布式·react native·react.js·wpf·harmonyos
donk13143 天前
React Native for OpenHarmony 实战:三方库 react-native-step-indicator 的鸿蒙化适配指南
分布式·react native·react.js·wpf·harmonyos
donk13143 天前
React Native for OpenHarmony 实战:三方库 react-native-segmented-control-tab 的鸿蒙化适配指南
javascript·react native·react.js·华为·harmonyos
donk13143 天前
React Native for OpenHarmony 实战:三方库 react-native-toast-message 的鸿蒙化适配指南
react native·react.js·音视频·harmonyos
墨狂之逸才4 天前
# React Native 0.59 在 Node 24 下的启动兼容问题:从报错到一条命令运行
react native
天道kabuto4 天前
入门 React Native:初始化 HelloRN 项目,Android 环境排错全记录
react native
程序员老刘6 天前
Flutter你看看人家RN
flutter·react native·ai编程
是你的小橘呀6 天前
告别各写各的!从 0 到 1 打造 React Native 客户端公共动效基础设施 🏗️
react native
墨狂之逸才6 天前
# React Native iOS 排查记录:从 Yoga 编译报错,到模拟器反复白屏
react native