diff --git a/docs/api/navigators/TabNavigator.md b/docs/api/navigators/TabNavigator.md
index 062122d..ebec7e2 100644
--- a/docs/api/navigators/TabNavigator.md
+++ b/docs/api/navigators/TabNavigator.md
@@ -87,6 +87,7 @@ The route configs object is a mapping from route name to a route config, which t
- `tabBarPosition` - Position of the tab bar, can be `'top'` or `'bottom'`.
- `swipeEnabled` - Whether to allow swiping between tabs.
- `animationEnabled` - Whether to animate when changing tabs.
+- `configureTransition` - a function that, given `currentTransitionProps` and `nextTransitionProps`, returns a configuration object that describes the animation between tabs.
- `lazy` - Whether to lazily render tabs as needed as opposed to rendering them upfront.
- `initialLayout` - Optional object containing the initial `height` and `width`, can be passed to prevent the one frame delay in [react-native-tab-view](https://github.com/react-native-community/react-native-tab-view#avoid-one-frame-delay) rendering.
- `tabBarOptions` - Configure the tab bar, see below.
diff --git a/examples/NavigationPlayground/js/App.js b/examples/NavigationPlayground/js/App.js
index ac849a2..94798b5 100644
--- a/examples/NavigationPlayground/js/App.js
+++ b/examples/NavigationPlayground/js/App.js
@@ -25,6 +25,7 @@ import StacksInTabs from './StacksInTabs';
import StacksOverTabs from './StacksOverTabs';
import SimpleStack from './SimpleStack';
import SimpleTabs from './SimpleTabs';
+import TabAnimations from './TabAnimations';
const ExampleRoutes = {
SimpleStack: {
@@ -90,6 +91,11 @@ const ExampleRoutes = {
screen: SimpleTabs,
path: 'settings',
},
+ TabAnimations: {
+ name: 'Animated Tabs Example',
+ description: 'Tab transitions have custom animations',
+ screen: TabAnimations,
+ },
};
const MainScreen = ({ navigation }) => (
diff --git a/examples/NavigationPlayground/js/TabAnimations.js b/examples/NavigationPlayground/js/TabAnimations.js
new file mode 100644
index 0000000..ebe2512
--- /dev/null
+++ b/examples/NavigationPlayground/js/TabAnimations.js
@@ -0,0 +1,126 @@
+/**
+ * @flow
+ */
+
+import React from 'react';
+import { Button, ScrollView, Animated } from 'react-native';
+import { StackNavigator, TabNavigator } from 'react-navigation';
+
+import Ionicons from 'react-native-vector-icons/Ionicons';
+import SampleText from './SampleText';
+
+const MyNavScreen = ({ navigation, banner }) => (
+
+ {banner}
+
+);
+
+const MyHomeScreen = ({ navigation }) => (
+
+);
+
+const MyProfileScreen = ({ navigation }) => (
+
+);
+
+const MyNotificationsSettingsScreen = ({ navigation }) => (
+
+);
+
+const MySettingsScreen = ({ navigation }) => (
+
+);
+
+const MainTab = StackNavigator({
+ Home: {
+ screen: MyHomeScreen,
+ path: '/',
+ navigationOptions: {
+ title: 'Welcome',
+ },
+ },
+ Profile: {
+ screen: MyProfileScreen,
+ path: '/people/:name',
+ navigationOptions: ({ navigation }) => ({
+ title: `${navigation.state.params.name}'s Profile!`,
+ }),
+ },
+});
+
+const SettingsTab = StackNavigator({
+ Settings: {
+ screen: MySettingsScreen,
+ path: '/',
+ navigationOptions: () => ({
+ title: 'Settings',
+ }),
+ },
+ NotifSettings: {
+ screen: MyNotificationsSettingsScreen,
+ navigationOptions: {
+ title: 'Notifications',
+ },
+ },
+});
+
+const TabAnimations = TabNavigator(
+ {
+ MainTab: {
+ screen: MainTab,
+ path: '/',
+ navigationOptions: {
+ tabBarLabel: 'Home',
+ tabBarIcon: ({ tintColor, focused }) => (
+
+ ),
+ },
+ },
+ SettingsTab: {
+ screen: SettingsTab,
+ path: '/settings',
+ navigationOptions: {
+ tabBarLabel: 'Settings',
+ tabBarIcon: ({ tintColor, focused }) => (
+
+ ),
+ },
+ },
+ },
+ {
+ tabBarPosition: 'bottom',
+ animationEnabled: true,
+ configureTransition: (currentTransitionProps,nextTransitionProps) => ({
+ timing: Animated.spring,
+ tension: 1,
+ friction: 35,
+ }),
+ swipeEnabled: false,
+ }
+);
+
+export default TabAnimations;
diff --git a/src/navigators/TabNavigator.js b/src/navigators/TabNavigator.js
index 2f72f41..6c39af9 100644
--- a/src/navigators/TabNavigator.js
+++ b/src/navigators/TabNavigator.js
@@ -48,6 +48,7 @@ const TabNavigator = (
tabBarOptions,
swipeEnabled,
animationEnabled,
+ configureTransition,
lazy,
initialLayout,
...tabsConfig
@@ -68,6 +69,7 @@ const TabNavigator = (
tabBarOptions={tabBarOptions}
swipeEnabled={swipeEnabled}
animationEnabled={animationEnabled}
+ configureTransition={configureTransition}
lazy={lazy}
initialLayout={initialLayout}
/>
diff --git a/src/views/TabView/TabView.js b/src/views/TabView/TabView.js
index 9aab73c..c9a26b6 100644
--- a/src/views/TabView/TabView.js
+++ b/src/views/TabView/TabView.js
@@ -22,6 +22,10 @@ export type TabViewConfig = {
tabBarOptions?: {},
swipeEnabled?: boolean,
animationEnabled?: boolean,
+ configureTransition?: (
+ currentTransitionProps: Object,
+ nextTransitionProps: Object
+ ) => Object,
lazy?: boolean,
initialLayout?: Layout,
};
@@ -39,6 +43,10 @@ type Props = {
tabBarOptions?: {},
swipeEnabled?: boolean,
animationEnabled?: boolean,
+ configureTransition?: (
+ currentTransitionProps: Object,
+ nextTransitionProps: Object
+ ) => Object,
lazy?: boolean,
initialLayout: Layout,
@@ -162,6 +170,7 @@ class TabView extends React.PureComponent {
tabBarComponent,
tabBarPosition,
animationEnabled,
+ configureTransition,
swipeEnabled,
lazy,
initialLayout,
@@ -189,7 +198,10 @@ class TabView extends React.PureComponent {
}
}
- if (animationEnabled === false && swipeEnabled === false) {
+ if (
+ (animationEnabled === false && swipeEnabled === false) ||
+ typeof configureTransition === 'function'
+ ) {
renderPager = this._renderPager;
}
@@ -197,6 +209,7 @@ class TabView extends React.PureComponent {
lazy,
initialLayout,
animationEnabled,
+ configureTransition,
swipeEnabled,
renderPager,
renderHeader,