跳至主要内容
版本:6.x

屏幕之间元素动画

本指南介绍如何在屏幕之间对元素进行动画处理。此功能称为共享元素过渡,它在@react-navigation/native-stack中使用React Native Reanimated实现。

警告

截至撰写本指南时,共享元素过渡被认为是实验性功能,不建议用于生产环境。

先决条件

在继续本指南之前,请确保您的应用程序满足以下条件

最小示例

要创建共享过渡

  1. 使用从 react-native-reanimated 导入的 Animated 组件。
  2. 将相同的 sharedTransitionTag 分配给不同屏幕上的元素。
  3. 在屏幕之间导航。过渡将自动开始。
import * as React from 'react';
import { View, Button, StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

import Animated from 'react-native-reanimated';

const Stack = createNativeStackNavigator();

function HomeScreen({ navigation }) {
return (
<View style={styles.container}>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
<Animated.Image
source={{ uri: 'https://picsum.photos/id/39/200' }}
style={{ width: 300, height: 300 }}
sharedTransitionTag="tag"
/>
</View>
);
}

function DetailsScreen({ navigation }) {
return (
<View style={styles.container}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<Animated.Image
source={{ uri: 'https://picsum.photos/id/39/200' }}
style={{ width: 100, height: 100 }}
sharedTransitionTag="tag"
/>
</View>
);
}

export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
},
});

sharedTransitionTag 是一个字符串,它必须在单个屏幕的上下文中是唯一的,但必须与屏幕之间的元素匹配。此属性允许 Reanimated 识别和动画化元素,类似于 key 属性,它告诉 React 列表中的哪个元素是哪个。

自定义过渡

默认情况下,过渡使用 withTiming 动画化 widthheightoriginXoriginYtransform 属性,持续时间为 500 毫秒。您可以轻松地自定义 widthheightoriginXoriginY 属性。自定义 transform 也是可能的,但这超出了本指南的范围。

警告

自定义 SharedTransition API 尚未最终确定,可能会在将来的版本中发生更改。

要自定义过渡,您需要传递除 transform 之外的所有属性。

import { SharedTransition } from 'react-native-reanimated';

const customTransition = SharedTransition.custom((values) => {
'worklet';
return {
height: withSpring(values.targetHeight),
width: withSpring(values.targetWidth),
originX: withSpring(values.targetOriginX),
originY: withSpring(values.targetOriginY),
};
});

function HomeScreen() {
return (
<Animated.Image
style={{ width: 300, height: 300 }}
sharedTransitionTag="tag"
sharedTransitionStyle={customTransition} // add this to both elements on both screens
/>
);
}

参考

您可以在 React Native Reanimated 文档 中找到完整的共享元素过渡参考。

替代方案

或者,您可以使用 react-native-shared-element 库,并使用 React Navigation 绑定,它在基于 JS 的 @react-navigation/stack 导航器中实现共享元素过渡。但是,此解决方案没有得到积极维护。

The react-native-navigation 也支持共享元素过渡。您可以阅读更多关于它的内容 这里.