Allow transition configuration between tabs (#2222)

* allow transition configuration between tabs

* we don't need to pass configureTransition to TabBarComponent

* Update TabAnimations.js

* Update TabNavigator.md
This commit is contained in:
Dave Rogers 2017-11-20 16:16:43 -07:00 committed by Vojtech Novak
parent 3cff180224
commit 0a662c9835
5 changed files with 149 additions and 1 deletions

View File

@ -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'`. - `tabBarPosition` - Position of the tab bar, can be `'top'` or `'bottom'`.
- `swipeEnabled` - Whether to allow swiping between tabs. - `swipeEnabled` - Whether to allow swiping between tabs.
- `animationEnabled` - Whether to animate when changing 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. - `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. - `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. - `tabBarOptions` - Configure the tab bar, see below.

View File

@ -25,6 +25,7 @@ import StacksInTabs from './StacksInTabs';
import StacksOverTabs from './StacksOverTabs'; import StacksOverTabs from './StacksOverTabs';
import SimpleStack from './SimpleStack'; import SimpleStack from './SimpleStack';
import SimpleTabs from './SimpleTabs'; import SimpleTabs from './SimpleTabs';
import TabAnimations from './TabAnimations';
const ExampleRoutes = { const ExampleRoutes = {
SimpleStack: { SimpleStack: {
@ -90,6 +91,11 @@ const ExampleRoutes = {
screen: SimpleTabs, screen: SimpleTabs,
path: 'settings', path: 'settings',
}, },
TabAnimations: {
name: 'Animated Tabs Example',
description: 'Tab transitions have custom animations',
screen: TabAnimations,
},
}; };
const MainScreen = ({ navigation }) => ( const MainScreen = ({ navigation }) => (

View File

@ -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 }) => (
<ScrollView>
<SampleText>{banner}</SampleText>
<Button
onPress={() => navigation.navigate('Profile', { name: 'Jordan' })}
title="Open profile screen"
/>
<Button
onPress={() => navigation.navigate('NotifSettings')}
title="Open notifications screen"
/>
<Button
onPress={() => navigation.navigate('SettingsTab')}
title="Go to settings tab"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</ScrollView>
);
const MyHomeScreen = ({ navigation }) => (
<MyNavScreen banner="Home Screen" navigation={navigation} />
);
const MyProfileScreen = ({ navigation }) => (
<MyNavScreen
banner={`${navigation.state.params.name}s Profile`}
navigation={navigation}
/>
);
const MyNotificationsSettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
);
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Screen" navigation={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 }) => (
<Ionicons
name={focused ? 'ios-home' : 'ios-home-outline'}
size={26}
style={{ color: tintColor }}
/>
),
},
},
SettingsTab: {
screen: SettingsTab,
path: '/settings',
navigationOptions: {
tabBarLabel: 'Settings',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={focused ? 'ios-settings' : 'ios-settings-outline'}
size={26}
style={{ color: tintColor }}
/>
),
},
},
},
{
tabBarPosition: 'bottom',
animationEnabled: true,
configureTransition: (currentTransitionProps,nextTransitionProps) => ({
timing: Animated.spring,
tension: 1,
friction: 35,
}),
swipeEnabled: false,
}
);
export default TabAnimations;

View File

@ -48,6 +48,7 @@ const TabNavigator = (
tabBarOptions, tabBarOptions,
swipeEnabled, swipeEnabled,
animationEnabled, animationEnabled,
configureTransition,
lazy, lazy,
initialLayout, initialLayout,
...tabsConfig ...tabsConfig
@ -68,6 +69,7 @@ const TabNavigator = (
tabBarOptions={tabBarOptions} tabBarOptions={tabBarOptions}
swipeEnabled={swipeEnabled} swipeEnabled={swipeEnabled}
animationEnabled={animationEnabled} animationEnabled={animationEnabled}
configureTransition={configureTransition}
lazy={lazy} lazy={lazy}
initialLayout={initialLayout} initialLayout={initialLayout}
/> />

View File

@ -22,6 +22,10 @@ export type TabViewConfig = {
tabBarOptions?: {}, tabBarOptions?: {},
swipeEnabled?: boolean, swipeEnabled?: boolean,
animationEnabled?: boolean, animationEnabled?: boolean,
configureTransition?: (
currentTransitionProps: Object,
nextTransitionProps: Object
) => Object,
lazy?: boolean, lazy?: boolean,
initialLayout?: Layout, initialLayout?: Layout,
}; };
@ -39,6 +43,10 @@ type Props = {
tabBarOptions?: {}, tabBarOptions?: {},
swipeEnabled?: boolean, swipeEnabled?: boolean,
animationEnabled?: boolean, animationEnabled?: boolean,
configureTransition?: (
currentTransitionProps: Object,
nextTransitionProps: Object
) => Object,
lazy?: boolean, lazy?: boolean,
initialLayout: Layout, initialLayout: Layout,
@ -162,6 +170,7 @@ class TabView extends React.PureComponent<Props> {
tabBarComponent, tabBarComponent,
tabBarPosition, tabBarPosition,
animationEnabled, animationEnabled,
configureTransition,
swipeEnabled, swipeEnabled,
lazy, lazy,
initialLayout, initialLayout,
@ -189,7 +198,10 @@ class TabView extends React.PureComponent<Props> {
} }
} }
if (animationEnabled === false && swipeEnabled === false) { if (
(animationEnabled === false && swipeEnabled === false) ||
typeof configureTransition === 'function'
) {
renderPager = this._renderPager; renderPager = this._renderPager;
} }
@ -197,6 +209,7 @@ class TabView extends React.PureComponent<Props> {
lazy, lazy,
initialLayout, initialLayout,
animationEnabled, animationEnabled,
configureTransition,
swipeEnabled, swipeEnabled,
renderPager, renderPager,
renderHeader, renderHeader,