diff --git a/ExNavigationBar.js b/ExNavigationBar.js
new file mode 100644
index 0000000..59ab634
--- /dev/null
+++ b/ExNavigationBar.js
@@ -0,0 +1,233 @@
+/**
+ * Copyright (c) 2015, Facebook, Inc. All rights reserved.
+ *
+ * Facebook, Inc. ("Facebook") owns all right, title and interest, including
+ * all intellectual property and other proprietary rights, in and to the React
+ * Native CustomComponents software (the "Software"). Subject to your
+ * compliance with these terms, you are hereby granted a non-exclusive,
+ * worldwide, royalty-free copyright license to (1) use and copy the Software;
+ * and (2) reproduce and distribute the Software as part of your own software
+ * ("Your Software"). Facebook reserves all rights not expressly granted to
+ * you in this license agreement.
+ *
+ * THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED.
+ * IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR
+ * EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+'use strict';
+
+var React = require('React');
+var NavigatorNavigationBarStylesAndroid = require('NavigatorNavigationBarStylesAndroid');
+var NavigatorNavigationBarStylesIOS = require('NavigatorNavigationBarStylesIOS');
+var Platform = require('Platform');
+var StaticContainer = require('StaticContainer.react');
+var StyleSheet = require('StyleSheet');
+var View = require('View');
+
+var { Map } = require('immutable');
+
+var COMPONENT_NAMES = ['Title', 'LeftButton', 'RightButton'];
+
+var NavigatorNavigationBarStyles = Platform.OS === 'android' ?
+ NavigatorNavigationBarStylesAndroid : NavigatorNavigationBarStylesIOS;
+
+var navStatePresentedIndex = function(navState) {
+ if (navState.presentedIndex !== undefined) {
+ return navState.presentedIndex;
+ }
+ // TODO: rename `observedTopOfStack` to `presentedIndex` in `NavigatorIOS`
+ return navState.observedTopOfStack;
+};
+
+var NavigatorNavigationBar = React.createClass({
+
+ propTypes: {
+ navigator: React.PropTypes.object,
+ routeMapper: React.PropTypes.shape({
+ Title: React.PropTypes.func.isRequired,
+ LeftButton: React.PropTypes.func.isRequired,
+ RightButton: React.PropTypes.func.isRequired,
+ }).isRequired,
+ navState: React.PropTypes.shape({
+ routeStack: React.PropTypes.arrayOf(React.PropTypes.object),
+ presentedIndex: React.PropTypes.number,
+ }),
+ navigationStyles: React.PropTypes.object,
+ style: View.propTypes.style,
+ },
+
+ statics: {
+ Styles: NavigatorNavigationBarStyles,
+ StylesAndroid: NavigatorNavigationBarStylesAndroid,
+ StylesIOS: NavigatorNavigationBarStylesIOS,
+ },
+
+ getDefaultProps() {
+ return {
+ navigationStyles: NavigatorNavigationBarStyles,
+ };
+ },
+
+ componentWillMount: function() {
+ this._components = {};
+ this._descriptors = {};
+
+ COMPONENT_NAMES.forEach(componentName => {
+ this._components[componentName] = new Map();
+ this._descriptors[componentName] = new Map();
+ });
+ },
+
+ _getReusableProps: function(
+ /*string*/componentName,
+ /*number*/index
+ ) /*object*/ {
+ if (!this._reusableProps) {
+ this._reusableProps = {};
+ }
+ var propStack = this._reusableProps[componentName];
+ if (!propStack) {
+ propStack = this._reusableProps[componentName] = [];
+ }
+ var props = propStack[index];
+ if (!props) {
+ props = propStack[index] = {style:{}};
+ }
+ return props;
+ },
+
+ _updateIndexProgress: function(
+ /*number*/progress,
+ /*number*/index,
+ /*number*/fromIndex,
+ /*number*/toIndex
+ ) {
+ var amount = toIndex > fromIndex ? progress : (1 - progress);
+ var oldDistToCenter = index - fromIndex;
+ var newDistToCenter = index - toIndex;
+ var interpolate;
+ if (oldDistToCenter > 0 && newDistToCenter === 0 ||
+ newDistToCenter > 0 && oldDistToCenter === 0) {
+ interpolate = this.props.navigationStyles.Interpolators.RightToCenter;
+ } else if (oldDistToCenter < 0 && newDistToCenter === 0 ||
+ newDistToCenter < 0 && oldDistToCenter === 0) {
+ interpolate = this.props.navigationStyles.Interpolators.CenterToLeft;
+ } else if (oldDistToCenter === newDistToCenter) {
+ interpolate = this.props.navigationStyles.Interpolators.RightToCenter;
+ } else {
+ interpolate = this.props.navigationStyles.Interpolators.RightToLeft;
+ }
+
+ COMPONENT_NAMES.forEach(function (componentName) {
+ var component = this._components[componentName].get(this.props.navState.routeStack[index]);
+ var props = this._getReusableProps(componentName, index);
+ if (component && interpolate[componentName](props.style, amount)) {
+ component.setNativeProps(props);
+ }
+ }, this);
+ },
+
+ updateProgress: function(
+ /*number*/progress,
+ /*number*/fromIndex,
+ /*number*/toIndex
+ ) {
+ var max = Math.max(fromIndex, toIndex);
+ var min = Math.min(fromIndex, toIndex);
+ for (var index = min; index <= max; index++) {
+ this._updateIndexProgress(progress, index, fromIndex, toIndex);
+ }
+ },
+
+ render: function() {
+ var navBarStyle = {
+ height: this.props.navigationStyles.General.TotalNavHeight,
+ };
+ var navState = this.props.navState;
+ var components = COMPONENT_NAMES.map(function (componentName) {
+ return navState.routeStack.map(
+ this._getComponent.bind(this, componentName)
+ );
+ }, this);
+
+ if (this.props.navState.routeStack.slice(-1)[0].showNavigationBar === false) {
+ return null;
+ } else if (this.props.navState.routeStack.slice(-1)[0].showNavigationBar === true) {
+ return (
+
+ {components}
+
+ );
+ } else {
+ if (this.props.navigator.props.showNavigationBar === false) {
+ return null;
+ } else {
+ return (
+
+ {components}
+
+ );
+ }
+ }
+ },
+
+ _getComponent: function(
+ /*string*/componentName,
+ /*object*/route,
+ /*number*/index
+ ) /*?Object*/ {
+ if (this._descriptors[componentName].includes(route)) {
+ return this._descriptors[componentName].get(route);
+ }
+
+ var rendered = null;
+
+ var content = this.props.routeMapper[componentName](
+ this.props.navState.routeStack[index],
+ this.props.navigator,
+ index,
+ this.props.navState
+ );
+ if (!content) {
+ return null;
+ }
+
+ var initialStage = index === navStatePresentedIndex(this.props.navState) ?
+ this.props.navigationStyles.Stages.Center :
+ this.props.navigationStyles.Stages.Left;
+ rendered = (
+ {
+ this._components[componentName] = this._components[componentName].set(route, ref);
+ }}
+ style={initialStage[componentName]}>
+ {content}
+
+ );
+
+ this._descriptors[componentName] = this._descriptors[componentName].set(route, rendered);
+ return rendered;
+ },
+
+});
+
+
+var styles = StyleSheet.create({
+ navBarContainer: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ backgroundColor: 'transparent',
+ },
+});
+
+module.exports = NavigatorNavigationBar;
diff --git a/ExNavigator.js b/ExNavigator.js
index f4fb42a..d61f7c9 100644
--- a/ExNavigator.js
+++ b/ExNavigator.js
@@ -16,6 +16,7 @@ import ExNavigatorMixin from './ExNavigatorMixin';
import ExNavigatorStyles from './ExNavigatorStyles';
import ExRouteRenderer from './ExRouteRenderer';
import ExSceneConfigs from './ExSceneConfigs';
+import ExNavigationBar from './ExNavigationBar';
import type * as ExRoute from './ExRoute';
@@ -38,7 +39,7 @@ export default class ExNavigator extends React.Component {
...Navigator.defaultProps,
showNavigationBar: true,
renderNavigationBar: props => {
- return
+ return
},
};
@@ -93,10 +94,6 @@ export default class ExNavigator extends React.Component {
}
_renderNavigationBar(): ?Navigator.NavigationBar {
- if (!this.props.showNavigationBar) {
- return null;
- }
-
return this.props.renderNavigationBar({
routeMapper: this._routeRenderer.navigationBarRouteMapper,
style: [ExNavigatorStyles.bar, this.props.navigationBarStyle],
diff --git a/package.json b/package.json
index f1c1748..8b26bb6 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,7 @@
"dependencies": {
"@exponent/react-native-responsive-image": "0.0.4",
"autobind-decorator": "^1.3.2",
+ "immutable": "^3.7.5",
"invariant": "^2.1.0",
"react-native-clone-referenced-element": "^1.0.0"
}