Improve StatusBar/Header Behavior (#2669)

* Track orientation change

* Add tests for withOrientation

* Better variable naming
This commit is contained in:
Spencer Carli
2017-09-29 16:11:30 -05:00
parent 89dc7214f1
commit 90acb9e406
7 changed files with 110 additions and 10 deletions

View File

@@ -83,7 +83,7 @@
"react": "16.0.0-alpha.12",
"react-native": "^0.48.4",
"react-native-vector-icons": "^4.2.0",
"react-test-renderer": "^15.6.1"
"react-test-renderer": "^16.0.0"
},
"jest": {
"notify": true,

View File

@@ -262,6 +262,7 @@ export type HeaderProps = {
NavigationStackScreenOptions
>,
style: ViewStyleProp,
isLandscape?: boolean,
};
/**

View File

@@ -9,6 +9,7 @@ import { Animated, Platform, StyleSheet, View } from 'react-native';
import HeaderTitle from './HeaderTitle';
import HeaderBackButton from './HeaderBackButton';
import HeaderStyleInterpolator from './HeaderStyleInterpolator';
import withOrientation from '../withOrientation';
import type {
NavigationScene,
@@ -281,14 +282,25 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
screenProps,
progress,
style,
isLandscape,
...rest
} = this.props;
const { options } = this.props.getScreenDetails(scene);
const headerStyle = options.headerStyle;
const landscapeAwareStatusBarHeight = isLandscape ? 0 : STATUSBAR_HEIGHT;
const containerStyles = [
styles.container,
{
paddingTop: landscapeAwareStatusBarHeight,
height: APPBAR_HEIGHT + landscapeAwareStatusBarHeight,
},
headerStyle,
style,
];
return (
<Animated.View {...rest} style={[styles.container, headerStyle, style]}>
<Animated.View {...rest} style={containerStyles}>
<View style={styles.appBar}>{appBar}</View>
</Animated.View>
);
@@ -315,9 +327,7 @@ if (Platform.OS === 'ios') {
const styles = StyleSheet.create({
container: {
paddingTop: STATUSBAR_HEIGHT,
backgroundColor: Platform.OS === 'ios' ? '#F7F7F7' : '#FFF',
height: STATUSBAR_HEIGHT + APPBAR_HEIGHT,
...platformContainerStyles,
},
appBar: {
@@ -353,4 +363,4 @@ const styles = StyleSheet.create({
},
});
export default Header;
export default withOrientation(Header);

View File

@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`it adds isLandscape to props 1`] = `
<View
isLandscape={false}
/>
`;

View File

@@ -0,0 +1,15 @@
import React from 'react';
import { View } from 'react-native';
import renderer from 'react-test-renderer';
import withOrientation, { isOrientationLandscape } from '../withOrientation';
test('it adds isLandscape to props', () => {
const WrappedComponent = withOrientation(View);
const rendered = renderer.create(<WrappedComponent />).toJSON();
expect(rendered).toMatchSnapshot();
});
test('calculates orientation correctly', () => {
const isLandscape = isOrientationLandscape({ width: 10, height: 1 });
expect(isLandscape).toBeTruthy();
});

View File

@@ -0,0 +1,55 @@
// @flow
import React from 'react';
import { Dimensions } from 'react-native';
import hoistNonReactStatic from 'hoist-non-react-statics';
type WindowDimensions = {
width: number,
height: number,
};
type InjectedProps = {
isLandscape: boolean,
};
type State = {
isLandscape: boolean,
};
export const isOrientationLandscape = ({
width,
height,
}: WindowDimensions): boolean => width > height;
export default function<T: *>(WrappedComponent: ReactClass<T & InjectedProps>) {
class withOrientation extends React.Component<void, T, State> {
state: State;
constructor() {
super();
const isLandscape = isOrientationLandscape(Dimensions.get('window'));
this.state = { isLandscape };
}
componentDidMount() {
Dimensions.addEventListener('change', this.handleOrientationChange);
}
componentWillUnmount() {
Dimensions.removeEventListener('change', this.handleOrientationChange);
}
handleOrientationChange = ({ window }: { window: WindowDimensions }) => {
const isLandscape = isOrientationLandscape(window);
this.setState({ isLandscape });
};
render() {
return <WrappedComponent {...this.props} {...this.state} />;
}
}
return hoistNonReactStatic(withOrientation, WrappedComponent);
}

View File

@@ -2287,6 +2287,18 @@ fbjs@0.8.12:
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
fbjs@^0.8.16:
version "0.8.16"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
fbjs@^0.8.9:
version "0.8.15"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.15.tgz#4f0695fdfcc16c37c0b07facec8cb4c4091685b9"
@@ -4587,12 +4599,12 @@ react-proxy@^1.1.7:
lodash "^4.6.1"
react-deep-force-update "^1.0.0"
react-test-renderer@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-15.6.1.tgz#026f4a5bb5552661fd2cc4bbcd0d4bc8a35ebf7e"
react-test-renderer@^16.0.0:
version "16.0.0"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.0.0.tgz#9fe7b8308f2f71f29fc356d4102086f131c9cb15"
dependencies:
fbjs "^0.8.9"
object-assign "^4.1.0"
fbjs "^0.8.16"
object-assign "^4.1.1"
react-timer-mixin@^0.13.2:
version "0.13.3"