You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用单个共享值为多视图设置动画样式(React Native Reanimated)

基于current状态计算React Native Reanimated v3菜单按钮透明度(替代多共享值)

我是React Native Reanimated v3的新手,希望根据当前聚焦的组件为菜单按钮设置透明度样式。目前我的实现代码如下:

type clist = 'one' | 'two' | 'three'
const opacityOne = useSharedValue(1)
const opacityTwo = useSharedValue(0.4)
const opacityThree = useSharedValue(0.4)
const [current, setCurrent] = useState<clist>('one')

const onPress = (screen:clist) => {
    setCurrent(screen)
    switch (screen) {
        case 'one':
            opacityOne.value = withTiming(1, {duration: 100})
            opacityTwo.value = withTiming(0.4, {duration: 100})
            opacityThree.value = withTiming(0.4, {duration: 100})
            navigation.navigate('One')
            break
        case 'two':
            opacityOne.value = withTiming(0.4, {duration: 100})
            opacityTwo.value = withTiming(1, {duration: 100})
            opacityThree.value = withTiming(0.4, {duration: 100})
            navigation.navigate('Two')
            break
        case 'three':
            opacityOne.value = withTiming(0.4, {duration: 100})
            opacityTwo.value = withTiming(0.4, {duration: 100})
            opacityThree.value = withTiming(1, {duration: 100})
            navigation.navigate('Three')
            break
    }
}

我想知道是否可以基于current状态计算opacity,而非使用三个独立的共享值?


当然可以,你只需要维护单个共享值存储当前选中项,然后通过动画样式直接计算每个按钮的透明度,无需多个独立的useSharedValue。以下是两种优化方案:

方案1:同步useState到共享值(兼容非动画逻辑)

适合需要在非动画场景中使用current状态的情况:

type clist = 'one' | 'two' | 'three';
const [current, setCurrent] = useState<clist>('one');
// 单个共享值存储当前选中项
const currentScreen = useSharedValue<clist>(current);

// 同步useState更新到共享值,触发透明度动画
useEffect(() => {
  currentScreen.value = withTiming(current, { duration: 100 });
}, [current]);

const onPress = (screen: clist) => {
  setCurrent(screen);
  navigation.navigate(screen as never);
};

// 为每个按钮生成动画样式
const getAnimatedButtonStyle = (screen: clist) => {
  return useAnimatedStyle(() => ({
    opacity: currentScreen.value === screen ? 1 : 0.4,
  }));
};

// 使用示例:
// <Animated.View style={getAnimatedButtonStyle('one')}>...</Animated.View>

方案2:直接用共享值管理状态(更简洁)

如果不需要在非动画逻辑中使用current,可以完全去掉useState,直接用共享值维护选中状态:

type clist = 'one' | 'two' | 'three';
const currentScreen = useSharedValue<clist>('one');

const onPress = (screen: clist) => {
  // 直接更新共享值,自动触发透明度平滑过渡
  currentScreen.value = withTiming(screen, { duration: 100 });
  navigation.navigate(screen as never);
};

// 单个按钮的动画样式示例
const oneButtonStyle = useAnimatedStyle(() => ({
  opacity: currentScreen.value === 'one' ? 1 : 0.4,
}));

原理说明

Reanimated会自动跟踪共享值的变化,当currentScreen通过withTiming更新时,所有依赖它的动画样式都会自动完成透明度的平滑过渡,完全替代了原来手动维护三个共享值的冗余逻辑。


内容的提问来源于stack exchange,提问作者Dalton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:02:04