React-native-reanimated 动画在 ios 上不起作用,在 android 上起作用

问题描述 投票:0回答:2

我有一个底部栏的动画,位于选项卡文本下方,该动画在 android 中工作正常,但在 ios 中不行。我正在使用react-native-reanimated。 任何帮助,将不胜感激。 谢谢

const MyTabBar = React.memo((props) => {


const {state, descriptors, navigation, position, setEnableSwipe, swipeEnabled, layout, theme, auth, ui} = props;
  if (state.routes[state.index].state && state.routes[state.index].state.index !== 0) {
    if (swipeEnabled === true) {
      setEnableSwipe(false)
    }
    return null;
  }
  else {
    if (swipeEnabled === false) {
      setEnableSwipe(true);
    }

    var tabWidth = (layout.width - 50)/3
    const left = Animated.interpolate(position, {
      inputRange: [0, 1, 2],
      outputRange: [(tabWidth - 50)/2 , tabWidth + (tabWidth - 50)/2, 2*tabWidth + (tabWidth - 50)/2]
    });
    const length = Animated.interpolate(position, {
      inputRange: [0, 0.5, 1, 1.5, 2],
      outputRange: [0.3, 1, 0.3, 1, 0.3],
    })
    return (
      <View style={{ flexDirection: 'row', backgroundColor: Platform.OS === 'ios' && ui.showing_modal ? 'white' : 'white', alignItems: 'center' }}>
        {state.routes.map((route, index) => {
          const { options } = descriptors[route.key];
          const label =
            options.tabBarLabel !== undefined
              ? options.tabBarLabel
              : options.title !== undefined
              ? options.title
              : route.name;
  
          const isFocused = state.index === index;
  
          const onPress = () => {
            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,
            });
          };

          const inputRange = state.routes.map((_, i) => i);
          const opacity = Animated.interpolate(position, {
            inputRange,
            outputRange: inputRange.map(i => (i === index ? 1 : 0.4)),
          });

          return (
            <TouchableOpacity
              accessibilityRole="button"
              accessibilityStates={isFocused ? ['selected'] : []}
              accessibilityLabel={options.tabBarAccessibilityLabel}
              testID={options.tabBarTestID}
              onPress={onPress}
              onLongPress={onLongPress}
              style={{flex: 1}}
            >
              <Animated.Text style={{ 
                opacity, 
                fontWeight: index === state.index ? '600' : 'normal', 
                fontSize: index === state.index ? 19 : 17,
                textAlign: 'center',
              }}>
                {label}
              </Animated.Text>
            </TouchableOpacity>
          );
        })}
         {Platform.OS === 'ios' && false ? 
      <View/> :  <Animated.View 
      style={{
        backgroundColor: theme.primaryColor, 
        translateX: left, 
        scaleX: length,
        height: 4, 
        width: 50, 
        position: 'absolute', 
        bottom: 0,
        borderRadius: 10,
      }} />}
        <TouchableOpacity 
          style={{minWidth: 50, maxWidth: 50}}
          onPress={() => {
            switch (state.index) {
              case 0:
                navigation.navigate('AddSchedule');
                break;
              case 1:
                navigation.navigate('AddScene');
                break;
              case 2:
                if (auth.accesstoken) {
                  navigation.navigate('NewGeoscene');
                } else {
                  ReactNativeHapticFeedback.trigger('notificationWarning', {
                    ignoreAndroidSystemSettings: true,
                    enableVibrateFallback: true
                  }) 
                }
                break;
              default:
                //
            }
          }}
        > 
          <Text style={{fontSize: 36, color: theme.primaryColor}}> + </Text>
        </TouchableOpacity>
      </View>
    );
  }
})

这是我的代码,Animated.View 行在 iOS 中没有动画,所以我没有在那里渲染它,但我希望它能工作。

安卓 Expected behaviour (android)

iOS: behaviour in iOS

ios react-native animation react-native-ios react-native-reanimated
2个回答
1
投票

我从我自己的代码中得到了一个观察结果,它可能适用也可能不适用于此处。仅当两个

transform
属性都使用react-native-reanimated 动画值时,此观察结果才成立。您的代码似乎符合此场景。

仅在 iOS 中,我必须

scale
属性放在
translateX
对象中的
transform
属性之前。如果我将
translateX
属性放在
scale
属性之前,则
translateX
属性将受到阻碍。

我对此没有解释,但我已经用

scaleX
测试过它,因为这就是你正在使用的,也是如此。

为了清楚起见,以下内容有效:

<Animated.Value
  style={[{
    transform: [{
      scale: animationValue1,
      translateX: animationValue2,
    }]
  }]}
/>

..在接下来的过程中,

scale
可以工作,但
translateX
不起作用:

<Animated.Value
  style={[{
    transform: [{
      translateX: animationValue2,
      scale: animationValue1,
    }]
  }]}
/>

您会注意到我的语法也与您的略有不同。据我所知,您不应该将

translateX
scaleX
属性放入
style
对象中,而不将其包装在
transform
属性中,如上所述。也许 reanimated 的
View
的工作方式与原生的原生工作方式略有不同。如果在尝试重新排序属性后它仍然不起作用,那么也请考虑一下。

请参阅此处的文档:https://reactnative.dev/docs/transforms#transform

这有点令人困惑,因为 API 将

transform
描述为一个函数,但页面顶部的示例显示了它的使用方式,就像我上面所做的那样。


0
投票

这是否意味着布局动画也可以重新启动 3。我遇到了同样的问题,在 android 上工作正常,但在 IOS 上却不行。

 <Animated.View entering={FadeInDown.duration(500)} style={{position:'absolute', bottom:50, width:'100%'}}>
      <Pressable
      style={({pressed})=>[styles.btn, pressed ? {opacity:.8} : '' ]}>
        <Text style={{alignSelf:'center', color:'#ffffff', fontSize:hp('2.5%'), fontWeight:'500', textTransform:'uppercase'}}>Buy Ticket</Text>
      </Pressable>
    </Animated.View>
© www.soinside.com 2019 - 2024. All rights reserved.