mirror of
https://github.com/status-im/react-navigation.git
synced 2025-02-25 01:28:16 +00:00
Change <Header /> layout back to absolute
(#562)
This commit is contained in:
parent
bbab489a6a
commit
e650f341e3
@ -58,6 +58,7 @@ type HeaderState = {
|
|||||||
|
|
||||||
const APPBAR_HEIGHT = Platform.OS === 'ios' ? 44 : 56;
|
const APPBAR_HEIGHT = Platform.OS === 'ios' ? 44 : 56;
|
||||||
const STATUSBAR_HEIGHT = Platform.OS === 'ios' ? 20 : 0;
|
const STATUSBAR_HEIGHT = Platform.OS === 'ios' ? 20 : 0;
|
||||||
|
const TITLE_OFFSET = Platform.OS === 'ios' ? 70 : 40;
|
||||||
|
|
||||||
class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||||
|
|
||||||
@ -121,8 +122,23 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
|||||||
const titleStyle = this._getHeaderTitleStyle(props.navigation);
|
const titleStyle = this._getHeaderTitleStyle(props.navigation);
|
||||||
const color = this._getHeaderTintColor(props.navigation);
|
const color = this._getHeaderTintColor(props.navigation);
|
||||||
const title = this._getHeaderTitle(props.navigation);
|
const title = this._getHeaderTitle(props.navigation);
|
||||||
|
|
||||||
|
// On iOS, width of left/right components depends on the calculated
|
||||||
|
// size of the title.
|
||||||
|
const onLayoutIOS = Platform.OS === 'ios'
|
||||||
|
? (e: LayoutEvent) => {
|
||||||
|
this.setState({
|
||||||
|
widths: {
|
||||||
|
...this.state.widths,
|
||||||
|
[props.key]: e.nativeEvent.layout.width,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HeaderTitle
|
<HeaderTitle
|
||||||
|
onLayout={onLayoutIOS}
|
||||||
style={[color ? { color } : null, titleStyle]}
|
style={[color ? { color } : null, titleStyle]}
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
@ -140,11 +156,15 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
|||||||
state: props.scenes[props.scene.index - 1].route,
|
state: props.scenes[props.scene.index - 1].route,
|
||||||
});
|
});
|
||||||
const backButtonTitle = this._getBackButtonTitle(previousNavigation);
|
const backButtonTitle = this._getBackButtonTitle(previousNavigation);
|
||||||
|
const width = this.state.widths[props.key]
|
||||||
|
? (props.layout.initWidth - this.state.widths[props.key]) / 2
|
||||||
|
: undefined;
|
||||||
return (
|
return (
|
||||||
<HeaderBackButton
|
<HeaderBackButton
|
||||||
onPress={props.onNavigateBack}
|
onPress={props.onNavigateBack}
|
||||||
tintColor={tintColor}
|
tintColor={tintColor}
|
||||||
title={backButtonTitle}
|
title={backButtonTitle}
|
||||||
|
width={width}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -161,9 +181,20 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderTitle(props: NavigationSceneRendererProps): ?React.Element<*> {
|
_renderTitle(props: NavigationSceneRendererProps, options: *): ?React.Element<*> {
|
||||||
|
const style = {};
|
||||||
|
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
if (!options.hasLeftComponent) {
|
||||||
|
style.left = 0;
|
||||||
|
}
|
||||||
|
if (!options.hasRightComponent) {
|
||||||
|
style.right = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return this._renderSubView(
|
return this._renderSubView(
|
||||||
props,
|
{ ...props, style },
|
||||||
'title',
|
'title',
|
||||||
this.props.renderTitleComponent,
|
this.props.renderTitleComponent,
|
||||||
this._renderTitleComponent,
|
this._renderTitleComponent,
|
||||||
@ -216,36 +247,20 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
|||||||
subView = defaultRenderer(subViewProps);
|
subView = defaultRenderer(subViewProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pointerEvents = offset !== 0 || isStale ? 'none' : 'box-none';
|
if (subView === null) {
|
||||||
|
return null;
|
||||||
// On iOS, width of left/right components depends on the calculated
|
|
||||||
// size of the title.
|
|
||||||
const onLayoutIOS = Platform.OS === 'ios' && name === 'title'
|
|
||||||
? (e: LayoutEvent) => {
|
|
||||||
this.setState({
|
|
||||||
widths: {
|
|
||||||
...this.state.widths,
|
|
||||||
[key]: e.nativeEvent.layout.width,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const titleWidth = name === 'left' || name === 'right'
|
const pointerEvents = offset !== 0 || isStale ? 'none' : 'box-none';
|
||||||
? this.state.widths[key]
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View
|
<Animated.View
|
||||||
pointerEvents={pointerEvents}
|
pointerEvents={pointerEvents}
|
||||||
onLayout={onLayoutIOS}
|
|
||||||
key={`${name}_${key}`}
|
key={`${name}_${key}`}
|
||||||
style={[
|
style={[
|
||||||
titleWidth && {
|
|
||||||
width: (props.layout.initWidth - titleWidth) / 2,
|
|
||||||
},
|
|
||||||
styles.item,
|
styles.item,
|
||||||
styles[name],
|
styles[name],
|
||||||
|
props.style,
|
||||||
styleInterpolator(props),
|
styleInterpolator(props),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
@ -257,15 +272,18 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
|||||||
_renderHeader(props: NavigationSceneRendererProps): React.Element<*> {
|
_renderHeader(props: NavigationSceneRendererProps): React.Element<*> {
|
||||||
const left = this._renderLeft(props);
|
const left = this._renderLeft(props);
|
||||||
const right = this._renderRight(props);
|
const right = this._renderRight(props);
|
||||||
const title = this._renderTitle(props);
|
const title = this._renderTitle(props, {
|
||||||
|
hasLeftComponent: !!left,
|
||||||
|
hasRightComponent: !!right,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[StyleSheet.absoluteFill, styles.header]}
|
style={[StyleSheet.absoluteFill, styles.header]}
|
||||||
key={`scene_${props.scene.key}`}
|
key={`scene_${props.scene.key}`}
|
||||||
>
|
>
|
||||||
{left}
|
|
||||||
{title}
|
{title}
|
||||||
|
{left}
|
||||||
{right}
|
{right}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@ -289,7 +307,7 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
|||||||
appBar = scenesProps.map(this._renderHeader, this);
|
appBar = scenesProps.map(this._renderHeader, this);
|
||||||
} else {
|
} else {
|
||||||
appBar = this._renderHeader({
|
appBar = this._renderHeader({
|
||||||
...this.props,
|
...NavigationPropTypes.extractSceneRendererProps(this.props),
|
||||||
position: new Animated.Value(this.props.scene.index),
|
position: new Animated.Value(this.props.scene.index),
|
||||||
progress: new Animated.Value(0),
|
progress: new Animated.Value(0),
|
||||||
});
|
});
|
||||||
@ -329,19 +347,30 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
},
|
},
|
||||||
title: Platform.OS === 'android'
|
title: {
|
||||||
? {
|
bottom: 0,
|
||||||
flex: 1,
|
left: TITLE_OFFSET,
|
||||||
alignItems: 'flex-start',
|
right: TITLE_OFFSET,
|
||||||
}
|
top: 0,
|
||||||
: {},
|
position: 'absolute',
|
||||||
|
alignItems: Platform.OS === 'android'
|
||||||
|
? 'flex-start'
|
||||||
|
: 'center',
|
||||||
|
},
|
||||||
left: {
|
left: {
|
||||||
alignItems: 'flex-start',
|
left: 0,
|
||||||
|
bottom: 0,
|
||||||
|
top: 0,
|
||||||
|
position: 'absolute',
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
alignItems: 'flex-end',
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
top: 0,
|
||||||
|
position: 'absolute',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ type Props = {
|
|||||||
title?: ?string,
|
title?: ?string,
|
||||||
tintColor?: ?string,
|
tintColor?: ?string,
|
||||||
truncatedTitle?: ?string,
|
truncatedTitle?: ?string,
|
||||||
|
width?: ?number,
|
||||||
};
|
};
|
||||||
|
|
||||||
type DefaultProps = {
|
type DefaultProps = {
|
||||||
@ -27,7 +28,6 @@ type DefaultProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
containerWidth?: number,
|
|
||||||
initialTextWidth?: number,
|
initialTextWidth?: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,6 +37,7 @@ class HeaderBackButton extends React.PureComponent<DefaultProps, Props, State> {
|
|||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
tintColor: PropTypes.string,
|
tintColor: PropTypes.string,
|
||||||
truncatedTitle: PropTypes.string,
|
truncatedTitle: PropTypes.string,
|
||||||
|
width: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -48,15 +49,6 @@ class HeaderBackButton extends React.PureComponent<DefaultProps, Props, State> {
|
|||||||
|
|
||||||
state = {};
|
state = {};
|
||||||
|
|
||||||
_onContainerLayout = (e: LayoutEvent) => {
|
|
||||||
if (Platform.OS !== 'ios') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
containerWidth: e.nativeEvent.layout.width,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
_onTextLayout = (e: LayoutEvent) => {
|
_onTextLayout = (e: LayoutEvent) => {
|
||||||
if (this.state.initialTextWidth) {
|
if (this.state.initialTextWidth) {
|
||||||
return;
|
return;
|
||||||
@ -67,10 +59,10 @@ class HeaderBackButton extends React.PureComponent<DefaultProps, Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { onPress, title, tintColor, truncatedTitle } = this.props;
|
const { onPress, width, title, tintColor, truncatedTitle } = this.props;
|
||||||
|
|
||||||
const renderTruncated = this.state.containerWidth && this.state.initialTextWidth
|
const renderTruncated = this.state.initialTextWidth && width
|
||||||
? this.state.containerWidth < this.state.initialTextWidth
|
? this.state.initialTextWidth > width
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -80,10 +72,7 @@ class HeaderBackButton extends React.PureComponent<DefaultProps, Props, State> {
|
|||||||
style={styles.container}
|
style={styles.container}
|
||||||
borderless
|
borderless
|
||||||
>
|
>
|
||||||
<View
|
<View style={styles.container}>
|
||||||
onLayout={this._onContainerLayout}
|
|
||||||
style={styles.container}
|
|
||||||
>
|
|
||||||
<Image
|
<Image
|
||||||
style={[
|
style={[
|
||||||
styles.icon,
|
styles.icon,
|
||||||
@ -94,7 +83,6 @@ class HeaderBackButton extends React.PureComponent<DefaultProps, Props, State> {
|
|||||||
/>
|
/>
|
||||||
{Platform.OS === 'ios' && title && (
|
{Platform.OS === 'ios' && title && (
|
||||||
<Text
|
<Text
|
||||||
ellipsizeMode="middle"
|
|
||||||
onLayout={this._onTextLayout}
|
onLayout={this._onTextLayout}
|
||||||
style={[styles.title, { color: tintColor }]}
|
style={[styles.title, { color: tintColor }]}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user