Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ class TitleAndButtonsContainer(context: Context) : ViewGroup(context) {
val rightBarWidth = rightButtonBar.measuredWidth
val leftBarWidth = leftButtonBar.measuredWidth
val isCenter = titleComponentAlignment == Alignment.Center
val isFill = titleComponentAlignment == Alignment.Fill
val titleHeightMeasureSpec = MeasureSpec.makeMeasureSpec(containerHeight, MeasureSpec.AT_MOST)
val titleWidthMeasureSpec = makeTitleAtMostWidthMeasureSpec(containerWidth, rightBarWidth, leftBarWidth, isCenter)
val titleWidthMeasureSpec = makeTitleAtMostWidthMeasureSpec(containerWidth, rightBarWidth, leftBarWidth, isCenter, isFill)
if (titleComponent is TitleBarReactView) {
titleComponent.centered = isCenter
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ typealias TitleRight = Int
typealias TitleTop = Int
typealias TitleBottom = Int

fun makeTitleAtMostWidthMeasureSpec(containerWidth: Int, rightBarWidth: Int, leftBarWidth: Int, isCenter: Boolean): Int {
fun makeTitleAtMostWidthMeasureSpec(containerWidth: Int, rightBarWidth: Int, leftBarWidth: Int, isCenter: Boolean, isFill: Boolean = false): Int {
return if (isCenter) {
View.MeasureSpec.makeMeasureSpec(containerWidth, View.MeasureSpec.AT_MOST)
} else {
View.MeasureSpec.makeMeasureSpec(containerWidth - rightBarWidth - leftBarWidth - 2 * DEFAULT_LEFT_MARGIN_PX, View.MeasureSpec.AT_MOST)
val availableWidth = containerWidth - rightBarWidth - leftBarWidth - 2 * DEFAULT_LEFT_MARGIN_PX
View.MeasureSpec.makeMeasureSpec(
availableWidth,
if (isFill) View.MeasureSpec.EXACTLY else View.MeasureSpec.AT_MOST
)
}
}

Expand Down
4 changes: 3 additions & 1 deletion ios/RNNReactTitleView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

@implementation RNNReactTitleView {
BOOL _fillParent;
CGFloat _expectedHeight;
}

- (NSString *)componentType {
Expand All @@ -10,7 +11,7 @@ - (NSString *)componentType {

- (CGSize)intrinsicContentSize {
if (_fillParent) {
return UILayoutFittingExpandedSize;
return CGSizeMake(UILayoutFittingExpandedSize.width, _expectedHeight > 0 ? _expectedHeight : 44);
} else {
return [super intrinsicContentSize];
}
Expand All @@ -19,6 +20,7 @@ - (CGSize)intrinsicContentSize {
- (void)setAlignment:(NSString *)alignment inFrame:(CGRect)frame {
if ([alignment isEqualToString:@"fill"]) {
_fillParent = YES;
_expectedHeight = frame.size.height;
self.translatesAutoresizingMaskIntoConstraints = NO;
self.sizeFlexibility = RCTRootViewSizeFlexibilityNone;
} else {
Expand Down
13 changes: 13 additions & 0 deletions playground/e2e/Options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ describe('Options', () => {
await expect(elementByLabel('Title Changed')).toBeVisible();
});

it('TopBar custom title with subtitle should be visible', async () => {
await elementById(TestIDs.GOTO_TOPBAR_TITLE_TEST).tap();
await expect(elementById(TestIDs.TOPBAR_TITLE_TEXT)).toBeVisible();
await expect(elementById(TestIDs.TOPBAR_TITLE_AVATAR)).toBeVisible();
});

it('TopBar custom title without subtitle should be visible', async () => {
await elementById(TestIDs.GOTO_TOPBAR_TITLE_TEST).tap();
await elementById(TestIDs.SET_TOPBAR_WITHOUT_SUBTITLE_BTN).tap();
await expect(elementById(TestIDs.TOPBAR_TITLE_TEXT)).toBeVisible();
await expect(elementById(TestIDs.TOPBAR_TITLE_AVATAR)).toBeVisible();
});

it('Popping screen with yellow box should not crash', async () => {
await elementById(TestIDs.SHOW_YELLOW_BOX_BTN).tap();
await elementById(TestIDs.PUSH_BTN).tap();
Expand Down
15 changes: 14 additions & 1 deletion playground/src/screens/OptionsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ const {
GOTO_SEARCHBAR_MODAL,
REPLACE_TAB_TEST_ID,
REPLACED_TAB,
GOTO_TOPBAR_TITLE_TEST,
} = testIDs;

interface Props extends NavigationProps {}
interface Props extends NavigationProps { }

export default class Options extends NavigationComponent<Props> {
static options() {
Expand Down Expand Up @@ -75,6 +76,11 @@ export default class Options extends NavigationComponent<Props> {
testID={SET_REACT_TITLE_VIEW}
onPress={this.setReactTitleView}
/>
<Button
label="TopBar Title Test"
testID={GOTO_TOPBAR_TITLE_TEST}
onPress={this.gotoTopBarTitleTest}
/>
<Button
label="Show Yellow Box"
testID={SHOW_YELLOW_BOX_BTN}
Expand Down Expand Up @@ -136,6 +142,13 @@ export default class Options extends NavigationComponent<Props> {
},
});

gotoTopBarTitleTest = () =>
Navigation.push(this, {
component: {
name: Screens.TopBarTitleTest,
},
});

hideSearchBar = () =>
Navigation.mergeOptions(this, {
topBar: {
Expand Down
1 change: 1 addition & 0 deletions playground/src/screens/Screens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ const Screens = {
SearchBar: 'SearchBar',
SearchBarModal: 'SearchBarModal',
TopBar: 'TopBar',
TopBarTitleTest: 'TopBarTitleTest',
};

export default Screens;
121 changes: 121 additions & 0 deletions playground/src/screens/TopBarTitleTestScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React from 'react';
import { View, Text } from 'react-native';
import { NavigationComponent, NavigationProps, Navigation as Nav } from 'react-native-navigation';
import Button from '../components/Button';
import Root from '../components/Root';
import Navigation from '../services/Navigation';
import testIDs from '../testIDs';

const {
TOPBAR_TITLE_TEXT,
TOPBAR_TITLE_AVATAR,
SET_TOPBAR_WITH_SUBTITLE_BTN,
SET_TOPBAR_WITHOUT_SUBTITLE_BTN,
} = testIDs;

// TopBar title component WITH subtitle
function TopBarWithSubtitle() {
return (
<View style={{ flex: 1 }}>
<View style={{ flexDirection: 'row' }}>
<View
testID={TOPBAR_TITLE_AVATAR}
style={{ alignSelf: 'center', marginRight: 20, width: 10, height: 10, backgroundColor: 'red' }}
/>
<View style={{ flex: 1, justifyContent: 'center' }}>
<Text testID={TOPBAR_TITLE_TEXT} numberOfLines={1}>
Title - pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas sed
</Text>
<Text numberOfLines={1}>Subtitle</Text>
</View>
</View>
</View>
);
}

// TopBar title component WITHOUT subtitle - this triggers the bug on Android
function TopBarWithoutSubtitle() {
return (
<View style={{ flex: 1 }}>
<View style={{ flexDirection: 'row' }}>
<View
testID={TOPBAR_TITLE_AVATAR}
style={{ alignSelf: 'center', marginRight: 20, width: 10, height: 10, backgroundColor: 'red' }}
/>
<View style={{ flex: 1, justifyContent: 'center' }}>
<Text testID={TOPBAR_TITLE_TEXT} numberOfLines={1}>
Title - pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas sed
</Text>
{/* No subtitle - this causes the bug on Android */}
</View>
</View>
</View>
);
}

Nav.registerComponent('TopBarWithSubtitle', () => TopBarWithSubtitle);
Nav.registerComponent('TopBarWithoutSubtitle', () => TopBarWithoutSubtitle);

interface Props extends NavigationProps { }

export default class TopBarTitleTestScreen extends NavigationComponent<Props> {
static options() {
return {
topBar: {
title: {
component: {
name: 'TopBarWithSubtitle',
alignment: 'fill',
},
},
},
};
}

constructor(props: Props) {
super(props);
Navigation.events().bindComponent(this);
}

render() {
return (
<Root componentId={this.props.componentId}>
<Button
label="With Subtitle"
testID={SET_TOPBAR_WITH_SUBTITLE_BTN}
onPress={this.setTopBarWithSubtitle}
/>
<Button
label="Without Subtitle (Bug Test)"
testID={SET_TOPBAR_WITHOUT_SUBTITLE_BTN}
onPress={this.setTopBarWithoutSubtitle}
/>
</Root>
);
}

setTopBarWithSubtitle = () =>
Navigation.mergeOptions(this, {
topBar: {
title: {
component: {
name: 'TopBarWithSubtitle',
alignment: 'fill',
},
},
},
});

setTopBarWithoutSubtitle = () =>
Navigation.mergeOptions(this, {
topBar: {
title: {
component: {
name: 'TopBarWithoutSubtitle',
alignment: 'fill',
},
},
},
});
}

14 changes: 9 additions & 5 deletions playground/src/screens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,21 @@ function registerScreens() {
() => require('../components/TopBarBackground').default
);
Navigation.registerComponent(Screens.Toast, () => require('./Toast').default);
Navigation.registerComponent(
Screens.TopBarTitleTest,
() => require('./TopBarTitleTestScreen').default
);

const { ContextProvider } = require('../context');
const ContextScreen = require('./ContextScreen').default;
Navigation.registerComponent(
Screens.ContextScreen,
() => (props) =>
(
<ContextProvider>
<ContextScreen {...props} />
</ContextProvider>
),
(
<ContextProvider>
<ContextScreen {...props} />
</ContextProvider>
),
() => ContextScreen
);

Expand Down
7 changes: 7 additions & 0 deletions playground/src/testIDs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,13 @@ const testIDs = {
REPLACE_TAB_TEST_ID: 'REPLACE_TAB_TEST_ID',
REPLACED_TAB: 'REPLACED_TAB',
MOUNTED_SCREENS_TEXT: 'MOUNTED_SCREENS_TEXT',

GOTO_TOPBAR_TITLE_TEST: 'GOTO_TOPBAR_TITLE_TEST',
TOPBAR_TITLE_TEXT: 'TOPBAR_TITLE_TEXT',
TOPBAR_TITLE_AVATAR: 'TOPBAR_TITLE_AVATAR',
SET_TOPBAR_WITH_SUBTITLE_BTN: 'SET_TOPBAR_WITH_SUBTITLE_BTN',
SET_TOPBAR_WITHOUT_SUBTITLE_BTN: 'SET_TOPBAR_WITHOUT_SUBTITLE_BTN',

SCREEN_ROOT: 'SCREEN_ROOT',
SCREEN_ROOT_LIST: 'SCREEN_ROOT_LIST',

Expand Down