React Navigation:将单独的过渡应用于场景
React Navigation: Applying separate transitions to scenes
我想为我的 React Native (iOS) 应用在 React Navigation 中的 StackNavigator 中的场景应用不同的过渡效果。
export const AppNavigator = StackNavigator({
Home: { screen: Home },
NewChild: { screen: NewChild },
Journal: { screen: Journal }
});
我可能希望 NewChild 从下往上加载,就像模式一样。或者我可能希望它从右向左滑入。如果可以定制就太好了。从文档来看,您似乎只能将整个 StackNavigation 设置为 card 或 modal。
正如您已经在文档中看到的那样,现在不可能。您可以跟踪 this issue and this issue requesting this feature. It's on the roadmap for v2,但由于 v1 尚未发布,您最好的选择可能是:
- 实施您自己的 transitionConfig 以某种方式处理每个屏幕。我不确定这是否可行。
- 使用 main issue 中的想法派生一个工具。或者简单地让你的 fork 特定于你的代码并维护它直到问题得到解决。
感谢线程中的每个人,它对我有用。
我有很多场景只由一个 StackNavigator 管理,我想为其中一些制作不同的动画。
首先,我在我的路由器中设置了一个常量,其中包括每个场景我想显示水平过渡:
const horizontalTransitionScenes = [
AddContact,
];
之后,我使用 StackNavigator 设计了我的应用程序路由器:
const App = StackNavigator({
AddContact: {
screen: AddContact,
},
EditContact: {
screen: EditContact,
},
});
我使用 CardStackStyleInterpolator 来修改场景之间的转换。我可以这样导入:import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';
我们现在可以将 transitionConfig 参数添加到我们的 StackNavigator 以根据我们的场景显示不同的动画:
const App = StackNavigator(
{
AddContact: {
screen: AddContact
},
EditContact: {
screen: EditContact
}
},
{
transitionConfig: (currentState: any) => {
if (
currentState.scenes[
currentState.scenes.length - 1
].route.routeName.includes(horizontalTransitionScenes)
) {
return {
screenInterpolator: CardStackStyleInterpolator.forHorizontal
};
}
return {
screenInterpolator: CardStackStyleInterpolator.forVertical
};
}
}
);
通过 StackNavigator 实现,您将能够为您想要的场景显示不同类型的动画。
祝你有美好的一天
我可以通过一些条件逻辑来完成这个,我们在 react-navigation
3.3.2
.
您必须从 react-native
导入 Easing
和 Animated
然后您可以按名称或索引(下面是按名称)有条件地渲染特定屏幕的转换.
通过在导航器 外部 声明配置,并使用 {}
切换 transitionSpec
它只会在该特定屏幕上触发 - 与screenInterpolator
的条件。
Screen1
到 Screen2
有动画,但 none 的其他屏幕有那个动画。
const screen2Config = {
duration: 300,
easing: Easing.out(Easing.poly(4)),
timing: Animated.timing,
};
export const ScreenStack = createStackNavigator({
Screen1: {
screen: Screen1,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Screen1',
headerTitleAllowFontScaling: false,
}),
},
Screen2: {
screen: Screen2,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Screen2',
headerTitleAllowFontScaling: false,
tabBarVisible: false,
}),
},
Screen3: {
screen: Screen3,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Screen3',
headerTitleAllowFontScaling: false,
}),
},
Screen4: {
screen: Screen4,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Screen4',
headerTitleAllowFontScaling: false,
}),
},
}, {
headerMode: 'float',
mode: 'modal',
transitionConfig: sceneProps => ({
transitionSpec: sceneProps.scene.route.routeName === 'Screen2' ? screen2Config : {},
screenInterpolator: (sceneProps) => {
if (sceneProps.scene.route.routeName === 'Screen2') {
const { layout, position, scene } = sceneProps;
const { index } = scene;
const width = layout.initWidth;
const translateX = position.interpolate({
inputRange: [index - 1, index, index + 1],
outputRange: [width, 0, 0],
});
const opacity = position.interpolate({
inputRange: [index - 1, index - 0.99, index],
outputRange: [0, 1, 1],
});
return { opacity, transform: [{ translateX }] };
}
},
}),
});
我想为我的 React Native (iOS) 应用在 React Navigation 中的 StackNavigator 中的场景应用不同的过渡效果。
export const AppNavigator = StackNavigator({
Home: { screen: Home },
NewChild: { screen: NewChild },
Journal: { screen: Journal }
});
我可能希望 NewChild 从下往上加载,就像模式一样。或者我可能希望它从右向左滑入。如果可以定制就太好了。从文档来看,您似乎只能将整个 StackNavigation 设置为 card 或 modal。
正如您已经在文档中看到的那样,现在不可能。您可以跟踪 this issue and this issue requesting this feature. It's on the roadmap for v2,但由于 v1 尚未发布,您最好的选择可能是:
- 实施您自己的 transitionConfig 以某种方式处理每个屏幕。我不确定这是否可行。
- 使用 main issue 中的想法派生一个工具。或者简单地让你的 fork 特定于你的代码并维护它直到问题得到解决。
感谢线程中的每个人,它对我有用。
我有很多场景只由一个 StackNavigator 管理,我想为其中一些制作不同的动画。
首先,我在我的路由器中设置了一个常量,其中包括每个场景我想显示水平过渡:
const horizontalTransitionScenes = [
AddContact,
];
之后,我使用 StackNavigator 设计了我的应用程序路由器:
const App = StackNavigator({
AddContact: {
screen: AddContact,
},
EditContact: {
screen: EditContact,
},
});
我使用 CardStackStyleInterpolator 来修改场景之间的转换。我可以这样导入:import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';
我们现在可以将 transitionConfig 参数添加到我们的 StackNavigator 以根据我们的场景显示不同的动画:
const App = StackNavigator(
{
AddContact: {
screen: AddContact
},
EditContact: {
screen: EditContact
}
},
{
transitionConfig: (currentState: any) => {
if (
currentState.scenes[
currentState.scenes.length - 1
].route.routeName.includes(horizontalTransitionScenes)
) {
return {
screenInterpolator: CardStackStyleInterpolator.forHorizontal
};
}
return {
screenInterpolator: CardStackStyleInterpolator.forVertical
};
}
}
);
通过 StackNavigator 实现,您将能够为您想要的场景显示不同类型的动画。
祝你有美好的一天
我可以通过一些条件逻辑来完成这个,我们在 react-navigation
3.3.2
.
您必须从 react-native
导入 Easing
和 Animated
然后您可以按名称或索引(下面是按名称)有条件地渲染特定屏幕的转换.
通过在导航器 外部 声明配置,并使用 {}
切换 transitionSpec
它只会在该特定屏幕上触发 - 与screenInterpolator
的条件。
Screen1
到 Screen2
有动画,但 none 的其他屏幕有那个动画。
const screen2Config = {
duration: 300,
easing: Easing.out(Easing.poly(4)),
timing: Animated.timing,
};
export const ScreenStack = createStackNavigator({
Screen1: {
screen: Screen1,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Screen1',
headerTitleAllowFontScaling: false,
}),
},
Screen2: {
screen: Screen2,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Screen2',
headerTitleAllowFontScaling: false,
tabBarVisible: false,
}),
},
Screen3: {
screen: Screen3,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Screen3',
headerTitleAllowFontScaling: false,
}),
},
Screen4: {
screen: Screen4,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Screen4',
headerTitleAllowFontScaling: false,
}),
},
}, {
headerMode: 'float',
mode: 'modal',
transitionConfig: sceneProps => ({
transitionSpec: sceneProps.scene.route.routeName === 'Screen2' ? screen2Config : {},
screenInterpolator: (sceneProps) => {
if (sceneProps.scene.route.routeName === 'Screen2') {
const { layout, position, scene } = sceneProps;
const { index } = scene;
const width = layout.initWidth;
const translateX = position.interpolate({
inputRange: [index - 1, index, index + 1],
outputRange: [width, 0, 0],
});
const opacity = position.interpolate({
inputRange: [index - 1, index - 0.99, index],
outputRange: [0, 1, 1],
});
return { opacity, transform: [{ translateX }] };
}
},
}),
});