Дизайн макета вкладки нарушен в iPhone X. Я использую реагировать-навигация / нижние вкладки: ^ 5.0.6 . Я использовал SafeAreaProvider в качестве оболочки. Вот мой код ниже.
HomeScreen. js
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
function notificationStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Notification"
component={NotificationScreen}
options={{
title: Constants.strings.notification,
headerLeft: () => (
<Image
style={style.headerIcon}
source={require('./image/top_bar/top_bar_notification_icon.png')}
/>
),
headerStyle: {
backgroundColor: Constants.color.bgColor,
},
headerTintColor: Constants.color.primaryColor,
headerTitleStyle: {
fontSize: Constants.dimensions.fontSize16,
fontFamily: Constants.fonts.fontFamilyBold,
},
}}
/>
</Stack.Navigator>
);
}
function feedStack({navigation}) {
return (
<Stack.Navigator initialRouteName="Feed">
<Stack.Screen
name="Feed"
component={FeedScreen}
options={{
title: Constants.strings.feed,
headerLeft: () => (
<Image
style={style.headerIcon}
source={require('./image/top_bar/top_bar_feed_icon.png')}
/>
),
headerRight: () => (
<TouchableOpacity
onPress={() => navigation.navigate('Search')}
style={{marginRight: 16}}>
<Image
style={style.overflowIcon}
source={require('./image/top_bar/top_bar_search_icon.png')}
/>
</TouchableOpacity>
),
headerStyle: {
backgroundColor: Constants.color.bgColor,
},
headerTintColor: Constants.color.primaryColor,
headerTitleStyle: {
fontSize: Constants.dimensions.fontSize16,
fontFamily: Constants.fonts.fontFamilyBold,
},
}}
/>
<Stack.Screen
name="Search"
component={SearchScreen}
options={{headerShown: false}}
/>
</Stack.Navigator>
);
}
function profileStack({navigation}) {
return (
<Stack.Navigator>
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={{
title: Constants.strings.profile,
headerLeft: () => (
<Image
style={style.headerIcon}
source={require('./image/top_bar/top_bar_profile_icon.png')}
/>
),
headerRight: () => (
<ProfileOverflowMenu
onChangePasswordClicked={() => {
navigation.navigate('ChangePassword');
}}
onLogOutClicked={() => {}}
/>
),
headerStyle: {
backgroundColor: Constants.color.bgColor,
},
headerTintColor: Constants.color.primaryColor,
headerTitleStyle: {
fontSize: Constants.dimensions.fontSize16,
fontFamily: Constants.fonts.fontFamilyBold,
},
}}
/>
</Stack.Navigator>
);
}
function homeTabNavigator() {
return (
<Tab.Navigator
initialRouteName="Feed"
tabBarOptions={{
style: {
backgroundColor: Constants.color.tabBarBgColor,
height: Constants.dimensions.tabBarHeight,
},
activeTintColor: Constants.color.activeTintColor,
inactiveTintColor: Constants.color.inactiveTintColor,
labelStyle: {
fontSize: Constants.dimensions.fontSize12,
fontFamily: Constants.fonts.fontFamilyLight,
marginBottom: Constants.dimensions.marginPadding8,
},
}}>
<Tab.Screen
name="Notification"
component={notificationStack}
options={{
tabBarLabel: Constants.strings.notification,
tabBarIcon: ({tintColor, focused}) => (
<Image
style={style.tabBarIcon}
source={
focused
? require('./image/tab_bar/tab_notification_active.png')
: require('./image/tab_bar/tab_notification_inactive.png')
}
/>
),
}}
/>
<Tab.Screen
name="Feed"
component={feedStack}
options={{
tabBarLabel: Constants.strings.feed,
tabBarIcon: ({tintColor, focused}) => (
<Image
style={style.tabBarIcon}
source={
focused
? require('./image/tab_bar/tab_feed_active.png')
: require('./image/tab_bar/tab_feed_inactive.png')
}
/>
),
}}
/>
<Tab.Screen
name="Profile"
component={profileStack}
options={{
tabBarLabel: Constants.strings.profile,
tabBarIcon: ({tintColor, focused}) => (
<Image
style={style.tabBarIcon}
source={
focused
? require('./image/tab_bar/tab_profile_active.png')
: require('./image/tab_bar/tab_profile_inactive.png')
}
/>
),
}}
/>
</Tab.Navigator>
);
}
class HomeScreen extends React.Component {
profileMenu = null;
setMenuRef = ref => {
this.profileMenu = ref;
};
hideMenu = () => {
this.profileMenu.hide();
};
showMenu = () => {
this.profileMenu.show();
};
render() {
return (
<SafeAreaProvider>
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={homeTabNavigator}
options={{headerShown: false}}
/>
<Stack.Screen
name="ChangePassword"
component={ChangePasswordScreen}
options={{
headerShown: true,
title: Constants.strings.change_password,
headerStyle: {
backgroundColor: Constants.color.bgColor,
},
headerTintColor: Constants.color.primaryColor,
headerTitleStyle: {
fontSize: Constants.dimensions.fontSize16,
fontFamily: Constants.fonts.fontFamilyBold,
},
}}
/>
</Stack.Navigator>
</NavigationContainer>
</SafeAreaProvider>
);
}
}
export default HomeScreen;
FeedScreen. js
const listData = [
{
key: '1',
title: 'Title One',
date: '24th Feb 2020',
body:
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.",
topic: 'Topic one',
},
{
key: '2',
title: 'Title Two',
date: '22nd Feb 2020',
body:
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
topic: 'Topic test',
},
{
key: '3',
title:
'Title Three to test the long title if it is rendering properly or not',
date: '19th Feb 2020',
body:
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
topic: 'Topic sports',
},
{
key: '4',
title: 'Title Four',
date: '17th Feb 2020',
body: 'This is a body.',
topic: 'Topic one',
},
{
key: '5',
title: 'This is a title',
date: '15th Feb 2020',
body:
"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.",
topic: 'Topic one',
},
{
key: '6',
title: 'Title',
date: '15th Feb 2020',
body:
"There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.",
topic: 'Topic information',
},
];
class FeedScreen extends React.Component {
// only renders each list item
renderRow({item}) {
const title = `${item.title}`;
const date = `${item.date}`;
const body = `${item.body}`;
const topic = `${item.topic}`;
let actualRowComponent = (
<View style={styles.feedRow}>
<View style={styles.feedItemTitleDateHolder}>
<Text
style={styles.feedItemTitleStyle}
numberOfLines={1}
ellipsizeMode={'tail'}>
{title}
</Text>
<Text style={styles.feedItemDateStyle}>{date}</Text>
</View>
<Text
style={styles.feedItemBodyStyle}
numberOfLines={5}
ellipsizeMode={'tail'}>
{body}
</Text>
<View style={styles.feedItemTopicHolder}>
<Text style={styles.feedItemTopicLabelStyle}>
{Constants.strings.topic}
</Text>
<Text style={styles.feedItemTopicLabelStyle}>
{Constants.strings.colon}
</Text>
<Text style={styles.feedItemTopicValueStyle}>{topic}</Text>
</View>
</View>
);
let touchableWrapperIos = (
<TouchableHighlight
activeOpacity={0.5}
underlayColor={'#FFFFFF00'}
onPress={() => {
//this._navigation.navigate('DetailsRoute', {...item});
}}>
{actualRowComponent}
</TouchableHighlight>
);
let touchableWrapperAndroid = (
<TouchableNativeFeedback
useForeground={true}
background={TouchableNativeFeedback.SelectableBackgroundBorderless()}
onPress={() => {
//this._navigation.navigate('DetailsRoute', {...item});
}}>
{actualRowComponent}
</TouchableNativeFeedback>
);
if (require('react-native').Platform.OS === 'ios') {
return touchableWrapperIos;
} else {
return touchableWrapperAndroid;
}
}
render() {
return (
<>
<StatusBar
barStyle="light-content"
hidden={false}
backgroundColor={Constants.color.statusBarColor}
translucent={false}
/>
<SafeAreaView style={styles.feedBg}>
<FlatList
style={styles.feedContainer}
data={listData}
keyExtractor={(item, index) => item.key}
renderItem={this.renderRow}
/>
</SafeAreaView>
</>
);
}
}
export default FeedScreen;
Вот скриншот, ниже которого я получаю iOS
![enter image description here](https://i.stack.imgur.com/VJZ7k.png)
Вот скриншот, ниже которого я получаю android
![enter image description here](https://i.stack.imgur.com/yXM7C.png)