mirror of
https://github.com/status-im/react-navigation.git
synced 2025-02-25 01:28:16 +00:00
Add back button label to header (#257)
This commit is contained in:
parent
4b2f94544a
commit
79f21277cb
@ -120,6 +120,7 @@ All `navigationOptions` for the `StackNavigator`:
|
|||||||
- `header` - a config object for the header bar:
|
- `header` - a config object for the header bar:
|
||||||
- `visible` - Boolean toggle of header visibility. Only works when `headerMode` is `screen`.
|
- `visible` - Boolean toggle of header visibility. Only works when `headerMode` is `screen`.
|
||||||
- `title` - Title string used by the navigation bar, or a custom React component
|
- `title` - Title string used by the navigation bar, or a custom React component
|
||||||
|
- `backTitle` - Title string used by the back button or `null` to disable label. Defaults to `title` value by default
|
||||||
- `right` - Custom React Element to display on the right side of the header
|
- `right` - Custom React Element to display on the right side of the header
|
||||||
- `left` - Custom React Element to display on the left side of the header
|
- `left` - Custom React Element to display on the left side of the header
|
||||||
- `style` - Style object for the navigation bar
|
- `style` - Style object for the navigation bar
|
||||||
|
@ -436,3 +436,14 @@ export type NavigationSceneRenderer = (
|
|||||||
export type NavigationStyleInterpolator = (
|
export type NavigationStyleInterpolator = (
|
||||||
props: NavigationSceneRendererProps,
|
props: NavigationSceneRendererProps,
|
||||||
) => Style;
|
) => Style;
|
||||||
|
|
||||||
|
export type LayoutEvent = {
|
||||||
|
nativeEvent: {
|
||||||
|
layout: {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
@ -20,11 +20,11 @@ import addNavigationHelpers from '../addNavigationHelpers';
|
|||||||
import type {
|
import type {
|
||||||
NavigationScene,
|
NavigationScene,
|
||||||
NavigationRouter,
|
NavigationRouter,
|
||||||
NavigationState,
|
|
||||||
NavigationAction,
|
NavigationAction,
|
||||||
NavigationScreenProp,
|
NavigationScreenProp,
|
||||||
NavigationSceneRendererProps,
|
NavigationSceneRendererProps,
|
||||||
NavigationStyleInterpolator,
|
NavigationStyleInterpolator,
|
||||||
|
LayoutEvent,
|
||||||
Style,
|
Style,
|
||||||
} from '../TypeDefinition';
|
} from '../TypeDefinition';
|
||||||
|
|
||||||
@ -34,9 +34,9 @@ type SubViewProps = NavigationSceneRendererProps & {
|
|||||||
onNavigateBack?: () => void,
|
onNavigateBack?: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Navigation = NavigationScreenProp<NavigationState, NavigationAction>;
|
type Navigation = NavigationScreenProp<*, NavigationAction>;
|
||||||
|
|
||||||
type SubViewRenderer = (subViewProps: SubViewProps) => ?React.Element<*>;
|
type SubViewRenderer = (subViewProps: SubViewProps) => ?React.Element<any>;
|
||||||
|
|
||||||
export type HeaderProps = NavigationSceneRendererProps & {
|
export type HeaderProps = NavigationSceneRendererProps & {
|
||||||
mode: HeaderMode,
|
mode: HeaderMode,
|
||||||
@ -50,10 +50,16 @@ export type HeaderProps = NavigationSceneRendererProps & {
|
|||||||
|
|
||||||
type SubViewName = 'left' | 'title' | 'right';
|
type SubViewName = 'left' | 'title' | 'right';
|
||||||
|
|
||||||
|
type HeaderState = {
|
||||||
|
widths: {
|
||||||
|
[key: number]: number,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
class Header extends React.Component<void, HeaderProps, void> {
|
class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||||
|
|
||||||
static HEIGHT = APPBAR_HEIGHT + STATUSBAR_HEIGHT;
|
static HEIGHT = APPBAR_HEIGHT + STATUSBAR_HEIGHT;
|
||||||
static Title = HeaderTitle;
|
static Title = HeaderTitle;
|
||||||
@ -72,13 +78,9 @@ class Header extends React.Component<void, HeaderProps, void> {
|
|||||||
|
|
||||||
props: HeaderProps;
|
props: HeaderProps;
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: HeaderProps, nextState: any): boolean {
|
state = {
|
||||||
return ReactComponentWithPureRenderMixin.shouldComponentUpdate.call(
|
widths: {},
|
||||||
this,
|
};
|
||||||
nextProps,
|
|
||||||
nextState
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getHeaderTitle(navigation: Navigation): ?string {
|
_getHeaderTitle(navigation: Navigation): ?string {
|
||||||
const header = this.props.router.getScreenConfig(navigation, 'header');
|
const header = this.props.router.getScreenConfig(navigation, 'header');
|
||||||
@ -91,6 +93,14 @@ class Header extends React.Component<void, HeaderProps, void> {
|
|||||||
return typeof title === 'string' ? title : undefined;
|
return typeof title === 'string' ? title : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getBackButtonTitle(navigation: Navigation): ?string {
|
||||||
|
const header = this.props.router.getScreenConfig(navigation, 'header') || {};
|
||||||
|
if (header.backTitle === null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return header.backTitle || this._getHeaderTitle(navigation);
|
||||||
|
}
|
||||||
|
|
||||||
_getHeaderTintColor(navigation: Navigation): ?string {
|
_getHeaderTintColor(navigation: Navigation): ?string {
|
||||||
const header = this.props.router.getScreenConfig(navigation, 'header');
|
const header = this.props.router.getScreenConfig(navigation, 'header');
|
||||||
if (header && header.tintColor) {
|
if (header && header.tintColor) {
|
||||||
@ -107,61 +117,53 @@ class Header extends React.Component<void, HeaderProps, void> {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderTitleComponent = (props: SubViewProps): React.Element<HeaderTitle> => {
|
_renderTitleComponent = (props: SubViewProps) => {
|
||||||
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);
|
||||||
return <HeaderTitle style={[color ? { color } : null, titleStyle]}>{title}</HeaderTitle>;
|
return (
|
||||||
|
<HeaderTitle
|
||||||
|
style={[color ? { color } : null, titleStyle]}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</HeaderTitle>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
_renderLeftComponent = (props: SubViewProps): ?React.Element<HeaderBackButton> => {
|
_renderLeftComponent = (props: SubViewProps) => {
|
||||||
if (props.scene.index === 0 || !props.onNavigateBack) {
|
if (props.scene.index === 0 || !props.onNavigateBack) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const tintColor = this._getHeaderTintColor(props.navigation);
|
const tintColor = this._getHeaderTintColor(props.navigation);
|
||||||
// @todo(grabobu):
|
const previousNavigation = addNavigationHelpers({
|
||||||
// We have implemented support for back button label (which works 100% fine),
|
...props.navigation,
|
||||||
// but when title is too long, it will overlap the <HeaderTitle />.
|
state: props.scenes[props.scene.index - 1].route,
|
||||||
// We had to revert the PR implementing that because of Android issues,
|
});
|
||||||
// I will land it this week and re-enable that for next release.
|
const backButtonTitle = this._getBackButtonTitle(previousNavigation);
|
||||||
//
|
|
||||||
// const previousNavigation = addNavigationHelpers({
|
|
||||||
// ...props.navigation,
|
|
||||||
// state: props.scenes[props.scene.index - 1].route,
|
|
||||||
// });
|
|
||||||
// const backButtonTitle = this._getHeaderTitle(previousNavigation);
|
|
||||||
return (
|
return (
|
||||||
<HeaderBackButton
|
<HeaderBackButton
|
||||||
onPress={props.onNavigateBack}
|
onPress={props.onNavigateBack}
|
||||||
tintColor={tintColor}
|
tintColor={tintColor}
|
||||||
|
title={backButtonTitle}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
_renderRightComponent = () => null;
|
_renderRightComponent = () => null;
|
||||||
|
|
||||||
_renderLeft = (props: NavigationSceneRendererProps): ?React.Element<*> => this._renderSubView(
|
_renderLeft(props: NavigationSceneRendererProps): ?React.Element<*> {
|
||||||
|
return this._renderSubView(
|
||||||
props,
|
props,
|
||||||
'left',
|
'left',
|
||||||
this.props.renderLeftComponent,
|
this.props.renderLeftComponent,
|
||||||
this._renderLeftComponent,
|
this._renderLeftComponent,
|
||||||
HeaderStyleInterpolator.forLeft,
|
HeaderStyleInterpolator.forLeft,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_renderTitle = (props: NavigationSceneRendererProps, options: *): ?React.Element<*> => {
|
_renderTitle(props: NavigationSceneRendererProps): ?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, style },
|
props,
|
||||||
'title',
|
'title',
|
||||||
this.props.renderTitleComponent,
|
this.props.renderTitleComponent,
|
||||||
this._renderTitleComponent,
|
this._renderTitleComponent,
|
||||||
@ -169,13 +171,15 @@ class Header extends React.Component<void, HeaderProps, void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderRight = (props: NavigationSceneRendererProps): ?React.Element<*> => this._renderSubView(
|
_renderRight(props: NavigationSceneRendererProps): ?React.Element<*> {
|
||||||
|
return this._renderSubView(
|
||||||
props,
|
props,
|
||||||
'right',
|
'right',
|
||||||
this.props.renderRightComponent,
|
this.props.renderRightComponent,
|
||||||
this._renderRightComponent,
|
this._renderRightComponent,
|
||||||
HeaderStyleInterpolator.forRight,
|
HeaderStyleInterpolator.forRight,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_renderSubView(
|
_renderSubView(
|
||||||
props: NavigationSceneRendererProps,
|
props: NavigationSceneRendererProps,
|
||||||
@ -212,16 +216,34 @@ class Header extends React.Component<void, HeaderProps, void> {
|
|||||||
subView = defaultRenderer(subViewProps);
|
subView = defaultRenderer(subViewProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subView === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pointerEvents = offset !== 0 || isStale ? 'none' : 'box-none';
|
const pointerEvents = offset !== 0 || isStale ? 'none' : 'box-none';
|
||||||
|
|
||||||
|
// On iOS, width of left/right components depends on the calculated
|
||||||
|
// size of the title.
|
||||||
|
const onLayoutIOS = name === 'title'
|
||||||
|
? (e: LayoutEvent) => {
|
||||||
|
this.setState({
|
||||||
|
widths: {
|
||||||
|
...this.state.widths,
|
||||||
|
[index]: e.nativeEvent.layout.width,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const titleWidth = name === 'left' || name === 'right'
|
||||||
|
? this.state.widths[index]
|
||||||
|
: 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],
|
||||||
styleInterpolator(props),
|
styleInterpolator(props),
|
||||||
@ -232,61 +254,55 @@ class Header extends React.Component<void, HeaderProps, void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): React.Element<*> {
|
_renderHeader(props: NavigationSceneRendererProps): React.Element<*> {
|
||||||
|
const left = this._renderLeft(props);
|
||||||
|
const right = this._renderRight(props);
|
||||||
|
const title = this._renderTitle(props);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[StyleSheet.absoluteFill, styles.header]}
|
||||||
|
key={`scene_${props.scene.key}`}
|
||||||
|
>
|
||||||
|
{left}
|
||||||
|
{title}
|
||||||
|
{right}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let appBar;
|
||||||
|
|
||||||
|
if (this.props.mode === 'float') {
|
||||||
|
const scenesProps: Array<NavigationSceneRendererProps> = this.props.scenes
|
||||||
|
.map((scene: NavigationScene, index: number) => ({
|
||||||
|
...NavigationPropTypes.extractSceneRendererProps(this.props),
|
||||||
|
scene,
|
||||||
|
index,
|
||||||
|
navigation: addNavigationHelpers({
|
||||||
|
...this.props.navigation,
|
||||||
|
state: scene.route,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
appBar = scenesProps.map(this._renderHeader, this);
|
||||||
|
} else {
|
||||||
|
appBar = this._renderHeader({
|
||||||
|
...this.props,
|
||||||
|
position: new Animated.Value(this.props.scene.index),
|
||||||
|
progress: new Animated.Value(0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const { scenes, scene, style, position, progress, ...rest } = this.props;
|
const { scenes, scene, style, position, progress, ...rest } = this.props;
|
||||||
|
|
||||||
let children = null;
|
|
||||||
|
|
||||||
if (this.props.mode === 'float') {
|
|
||||||
// eslint-disable-next-line no-shadow
|
|
||||||
const scenesProps = (scenes.map((scene: NavigationScene, index: number) => {
|
|
||||||
const props = NavigationPropTypes.extractSceneRendererProps(this.props);
|
|
||||||
props.scene = scene;
|
|
||||||
props.index = index;
|
|
||||||
props.navigation = addNavigationHelpers({
|
|
||||||
...this.props.navigation,
|
|
||||||
state: scene.route,
|
|
||||||
});
|
|
||||||
return props;
|
|
||||||
}): Array<NavigationSceneRendererProps>);
|
|
||||||
const leftComponents = scenesProps.map(this._renderLeft, this);
|
|
||||||
const rightComponents = scenesProps.map(this._renderRight, this);
|
|
||||||
const titleComponents = scenesProps.map((props: *, i: number) =>
|
|
||||||
this._renderTitle(props, {
|
|
||||||
hasLeftComponent: leftComponents && !!leftComponents[i],
|
|
||||||
hasRightComponent: rightComponents && !!rightComponents[i],
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
children = [
|
|
||||||
titleComponents,
|
|
||||||
leftComponents,
|
|
||||||
rightComponents
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
const staticRendererProps = {
|
|
||||||
...this.props,
|
|
||||||
position: new Animated.Value(scene.index),
|
|
||||||
progress: new Animated.Value(0),
|
|
||||||
};
|
|
||||||
const leftComponent = this._renderLeft(staticRendererProps);
|
|
||||||
const rightComponent = this._renderRight(staticRendererProps);
|
|
||||||
const titleComponent = this._renderTitle(staticRendererProps, {
|
|
||||||
hasLeftComponent: !!leftComponent,
|
|
||||||
hasRightComponent: !!rightComponent,
|
|
||||||
});
|
|
||||||
|
|
||||||
children = [
|
|
||||||
titleComponent,
|
|
||||||
leftComponent,
|
|
||||||
rightComponent
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View {...rest} style={[styles.container, style]}>
|
<Animated.View {...rest} style={[styles.container, style]}>
|
||||||
<View style={styles.appBar}>{children}</View>
|
<View style={styles.appBar}>
|
||||||
|
{appBar}
|
||||||
|
</View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -295,8 +311,8 @@ class Header extends React.Component<void, HeaderProps, void> {
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
paddingTop: STATUSBAR_HEIGHT,
|
paddingTop: STATUSBAR_HEIGHT,
|
||||||
height: STATUSBAR_HEIGHT + APPBAR_HEIGHT,
|
|
||||||
backgroundColor: Platform.OS === 'ios' ? '#EFEFF2' : '#FFF',
|
backgroundColor: Platform.OS === 'ios' ? '#EFEFF2' : '#FFF',
|
||||||
|
height: STATUSBAR_HEIGHT + APPBAR_HEIGHT,
|
||||||
shadowColor: 'black',
|
shadowColor: 'black',
|
||||||
shadowOpacity: 0.1,
|
shadowOpacity: 0.1,
|
||||||
shadowRadius: StyleSheet.hairlineWidth,
|
shadowRadius: StyleSheet.hairlineWidth,
|
||||||
@ -306,30 +322,25 @@ const styles = StyleSheet.create({
|
|||||||
elevation: 4,
|
elevation: 4,
|
||||||
},
|
},
|
||||||
appBar: {
|
appBar: {
|
||||||
flex: 1
|
flex: 1,
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
flexDirection: 'row',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
bottom: 0,
|
|
||||||
left: 40,
|
|
||||||
position: 'absolute',
|
|
||||||
right: 40,
|
|
||||||
top: 0,
|
|
||||||
},
|
},
|
||||||
|
title: Platform.OS === 'android'
|
||||||
|
? {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
}
|
||||||
|
: null,
|
||||||
left: {
|
left: {
|
||||||
bottom: 0,
|
alignItems: 'flex-start',
|
||||||
left: 0,
|
|
||||||
position: 'absolute',
|
|
||||||
top: 0,
|
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
bottom: 0,
|
alignItems: 'flex-end',
|
||||||
position: 'absolute',
|
|
||||||
right: 0,
|
|
||||||
top: 0,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -10,54 +10,107 @@ import {
|
|||||||
StyleSheet,
|
StyleSheet,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
|
import type { LayoutEvent } from '../TypeDefinition';
|
||||||
|
|
||||||
import TouchableItem from './TouchableItem';
|
import TouchableItem from './TouchableItem';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onPress?: () => void,
|
onPress?: () => void,
|
||||||
title?: string,
|
title?: ?string,
|
||||||
tintColor?: ?string;
|
tintColor?: ?string,
|
||||||
|
truncatedTitle?: ?string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const HeaderBackButton = ({ onPress, title, tintColor }: Props) => (
|
type DefaultProps = {
|
||||||
<TouchableItem
|
tintColor: ?string,
|
||||||
delayPressIn={0}
|
truncatedTitle: ?string,
|
||||||
onPress={onPress}
|
|
||||||
style={styles.container}
|
|
||||||
borderless
|
|
||||||
>
|
|
||||||
<View style={styles.container}>
|
|
||||||
<Image
|
|
||||||
style={[
|
|
||||||
styles.icon,
|
|
||||||
title && styles.iconWithTitle,
|
|
||||||
{ tintColor },
|
|
||||||
]}
|
|
||||||
source={require('./assets/back-icon.png')}
|
|
||||||
/>
|
|
||||||
{Platform.OS === 'ios' && title && (
|
|
||||||
<Text style={[styles.title, { color: tintColor }]}>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</TouchableItem>
|
|
||||||
);
|
|
||||||
|
|
||||||
HeaderBackButton.propTypes = {
|
|
||||||
onPress: PropTypes.func.isRequired,
|
|
||||||
tintColor: PropTypes.string,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HeaderBackButton.defaultProps = {
|
type State = {
|
||||||
tintColor: Platform.select({
|
containerWidth?: number,
|
||||||
ios: '#037aff',
|
initialTextWidth?: number,
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HeaderBackButton extends React.PureComponent<DefaultProps, Props, State> {
|
||||||
|
static propTypes = {
|
||||||
|
onPress: PropTypes.func.isRequired,
|
||||||
|
title: PropTypes.string,
|
||||||
|
tintColor: PropTypes.string,
|
||||||
|
truncatedTitle: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
tintColor: Platform.select({
|
||||||
|
ios: '#037aff',
|
||||||
|
}),
|
||||||
|
truncatedTitle: 'Back',
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {};
|
||||||
|
|
||||||
|
_onContainerLayout = (e: LayoutEvent) => {
|
||||||
|
if (Platform.OS !== 'ios') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
containerWidth: e.nativeEvent.layout.width,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_onTextLayout = (e: LayoutEvent) => {
|
||||||
|
if (this.state.initialTextWidth) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
initialTextWidth: e.nativeEvent.layout.x + e.nativeEvent.layout.width,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { onPress, title, tintColor, truncatedTitle } = this.props;
|
||||||
|
|
||||||
|
const renderTruncated = this.state.containerWidth && this.state.initialTextWidth
|
||||||
|
? this.state.containerWidth < this.state.initialTextWidth
|
||||||
|
: false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableItem
|
||||||
|
delayPressIn={0}
|
||||||
|
onPress={onPress}
|
||||||
|
style={styles.container}
|
||||||
|
borderless
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
onLayout={this._onContainerLayout}
|
||||||
|
style={styles.container}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
style={[
|
||||||
|
styles.icon,
|
||||||
|
title && styles.iconWithTitle,
|
||||||
|
{ tintColor },
|
||||||
|
]}
|
||||||
|
source={require('./assets/back-icon.png')}
|
||||||
|
/>
|
||||||
|
{Platform.OS === 'ios' && title && (
|
||||||
|
<Text
|
||||||
|
ellipsizeMode="middle"
|
||||||
|
onLayout={this._onTextLayout}
|
||||||
|
style={[styles.title, { color: tintColor }]}
|
||||||
|
numberOfLines={1}
|
||||||
|
>
|
||||||
|
{renderTruncated ? truncatedTitle : title}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</TouchableItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
|
@ -23,7 +23,6 @@ const HeaderTitle = ({ style, ...rest }: Props) => (
|
|||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
title: {
|
title: {
|
||||||
flex: 1,
|
|
||||||
fontSize: Platform.OS === 'ios' ? 17 : 18,
|
fontSize: Platform.OS === 'ios' ? 17 : 18,
|
||||||
fontWeight: Platform.OS === 'ios' ? '600' : '500',
|
fontWeight: Platform.OS === 'ios' ? '600' : '500',
|
||||||
color: 'rgba(0, 0, 0, .9)',
|
color: 'rgba(0, 0, 0, .9)',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user