React navigation header title cut off - android

So basically i'm in the process of learning react native. I'm using the react navigation package and I just want to display a simple header title on my stack navigator but the title cuts off. Stack nav title
This is my App.js
import React from 'react';
import { View, Text } from 'react-native';
import { createStackNavigator, createAppContainer} from 'react-navigation'
import HomeScreen from './screens/HomeScreen'
import DetailsScreen from './screens/DetailsScreen'
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
},
{
initialRouteName: 'Home'
}
);
const AppContainer = createAppContainer(RootStack)
export default class App extends React.Component {
render(){
return<AppContainer />
}
}
and this is my HomeScreen.js
import React from 'react'
import {Button, View, Text } from 'react-native'
export default class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
}
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screeeen</Text>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
)
}
}
It doesnt look like this on my friends phones. I'm using a OnePlus 6 with android 9. They are on older versions of android could that be causing something?

Turns out this is a specific problem affecting OnePlus user who has chosen to use the font OnePlus Slate instead of for exmaple robot. Changing the font in the phone fixes the problem, alternatively you force the usage of a font in the app and it should work as well

I got the same problem running on a OnePlus phone and solved it without the font loader but style with the navigation option in headerTitleStyle width like so:
import { Dimensions } from 'react-native';
const WIDTH = Dimensions.get('window').width;
export const MyStackNav = createStackNavigator(
{
Tab1: {
screen: Tab1,
navigationOptions: ({ navigation }) => ({
headerTitle: `${navigation.state.routeName} page`,
headerTitleStyle: {
width: WIDTH - 75,
},
}),
},
...more code
}

A similar issue also occurs in various components like button in one plus devices. One way to solve it by giving some minimum width to the label style, so that you don't have to switch the font family, helps if you are using some custom fonts
Solution: width: '100%' or some fixed value like minWidth: 100
Code example in drawer navigation
<DrawerItem
labelStyle={{ minWidth: 100 }}
label={`Orders`}
onPress={() => {}}
/>

Related

CodeWithMosh: building the listing screen Padding problem with iOS and Android not outputting the same result

In his video, in the last part, he says that at the time of his Recording in iOS the padding is not applying when he applies it in the Screen component, but it actually works on Android. And at the end, when you do exactly what he suggests, a double layer of padding is added in the Android version.
import React from 'react';
import { View, SafeAreaView, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
function SafeScreen({children, style}) {
return (
<SafeAreaView style={[styles.screen, style]}>
<View style={style}>{children}</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
screen: {
paddingTop: Constants.statusBarHeight,
flex: 1,
}
})
export default SafeScreen;
I did find the Fix myself so look at my answer.
Here is the Fix that I did:
import React from 'react';
import { View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
function SafeScreen({children, style}) {
return (
<View style={[styles.screen ,style]}>{children}</View>
);
}
const styles = StyleSheet.create({
screen: {
paddingTop: Constants.statusBarHeight,
flex: 1,
},
})
export default SafeScreen;
Just simply don't use the SafeAreaView by React Native and instead apply the screen styling to the View.

Navigating from a FlatList Items exists in a Tab, to another Stack Screen

How The App works!
I have an app that shows a list of names and after that shows the meaning of the Name depends on some preference the user choose it from a dropDowns.
So in total there is a Main of 3 Screens!
First: is the UI screen that asks user to choose data,
Second: is the screen that holds a list contains names, I list them using a FlatList (BTW the data retrives from a SqLite -not important-)
Third: is the Screen that shows the name's meaning,
I am navigating from the "Main-Screen" to the "NameList-Screen" then To the "NameMeaning-Screen",
The navigation to the "NameMeaning-Screen" done by pressing on an item from the List.
Till here the app working nicely!
I decided to add a new feature to the app and that to show all the names i have in my DB and show it in a screen that have two Tabs, The first tab shows male's names and the second tab shows the female's names.
I did that step too.
But What am facing now is!
I want to navigate from that tabs when pressing on an item from the flatList, and navigate to the "Third Screen" I mentioned above the name's meaning!
But it gave error that, there is no such screen called "NameMeaing" and then it says " Name screen Its not handled by any navigator", So as much as i understand, when am in the Tabs the program have no access to the stack Navigator and cuz of this it gives that error.
As much as i was able to find on Web, There is examples of navigating from tabs to another stack screens, but in the all the examples, the tabs were the main screen in the applicaiton, but in my case i reach the tabs after pressing a certain button and navigate to another stacked screen.
As a soluation for the problem i thought about creating a secondry stack navigator inside my Tabs.js file that contains the tabs but i couldnt, then i thought i should create a Tab navigator in my App.js adding it to my stack navigator that already exists there and compine them in a navigator container. Maybe this is the soluation but i couldnt complete the code and connect the dots. Any help please?!
This is a video of the app while working (The scenario)
https://youtu.be/dBLNF5zMCt0
This is the Error it shows:
Error when i try to navigate from a tab screen to another different screen
This is App.js file
import 'react-native-gesture-handler';
import React, {Component} from 'react';
import {createStackNavigator} from 'react-navigation-stack';
import {createAppContainer} from 'react-navigation';
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
import MainScreen from './MainScreen';
import NamesList from './NamesList';
import NameMeaning from './NameMeaning';
import NameListWithTabsAgirlAboy from './NameListWithTabsAgirlAboy';
const App = createStackNavigator(
{
MainScreen: {
screen: MainScreen,
navigationOptions: {
header: null,
},
},
NamesList: {
screen: NamesList,
navigationOptions: {
header: null,
},
},
NameListWithTabsAgirlAboy: {
screen: NameListWithTabsAgirlAboy,
navigationOptions: {
header: null,
},
},
NameMeaning: {
screen: NameMeaning,
navigationOptions: {
header: null,
},
},
},
{
initialRouteName: 'MainScreen',
}
);
export default createAppContainer(App);
This is NameMeaninng.js file
class NameMeaning extends Component {
constructor(props) {
super(props);
}
render() {
const {navigation} = this.props;
return(
<SafeAreaView style= {styles.container}>
<Text style={styles.title}>معنى اسم {JSON.stringify(navigation.getParam('nameTitle', 'NO-ID'))}</Text>
<ScrollView style={styles.scrollView}>
<Text style={styles.text}>
{JSON.stringify(navigation.getParam('explaination', 'NO-ID'))}
</Text>
</ScrollView>
</SafeAreaView>
);
}
}
this is parts of Tabs.js file
This file have three classes in totall. BoysScreen, GirlsScreen and Tabs classes..
class BoysScreen extends React.Component {
constructor(props) {
super(props);
const {navigation} = this.props;
}
render() {
let FlatListNames = [];
FlatListNames = boysNames();
const {navigation} = this.props;
function Item({ title }, {navigation}) {
return (
<View style = {StyleSheet.item}>
<Text styel = {styles.title}> {title} </Text>
<Text style ={StyleSheet.explain}>اضغط للشرح</Text>
</View>
)
}
function boysNames() {
var boysNamesList = [];
db.transaction(tx => {
// boys names
tx.executeSql('SELECT ID, Name, Explanation FROM Names WHERE NameSex=?', ["لـ طفلي"], (tx, results) => {
for (let i = 0; i < results.rows.length; ++i) {
boysNamesList.push(results.rows.item(i));
}
});
}); // DB transaction
return boysNamesList;
};
return(
<View style= {styles.container}>
<FlatList
data={FlatListNames}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) =>
<TouchableOpacity
onPress = {() => {this.props.navigation.navigate('NameMeaning',{
nameTitle : item.Name,
nameId : item.ID,
explaination : item.Explanation,
});
}}
>
<Item title = {item.Name}/>
</TouchableOpacity>
}
/>
</View>
);
}
}// ends of BoysScreen Class
class Tabs extends React.Component {
constructor(props){
super(props);
}
render() {
const Tab = createMaterialTopTabNavigator();
// I have tried to create a stack here but it gave errors and couldnt solve it
//cont Stack = createStackNavigator();
return(
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name ="FemaleNames" component = {GirlsScreen} /> //GirlsScreen is a class
<Tab.Screen name = "MaleNames" component = {BoysScreen} /> // BoysScreen is a class
</Tab.Navigator>
// I have tried to import NameMeanig class and navigate to it like this, but it gaves errors too.
//<Stack.Screen name="Home" component={NameMeaning} />
</NavigationContainer>
);
}
Thanks in advance, any help of how i can build this algorithm is appricated really..
It was a problem with version compatibility, i was using React navigation V4 and V5 alltogether, After Searching more i have solved it in this way, Changing App.js and compine all the stacks and tabs navigators in App.js
Credit to this guy : https://www.youtube.com/watch?v=nQVCkqvU1uE
import 'react-native-gesture-handler';
import React, {Component} from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
import MainScreen from './App/components/Home/MainScreen';
import NamesList from './App/components/NameList/NamesList';
import NameMeaning from './App/components/NameMeaning/NameMeaning';
import GirlNamesScreen from './App/components/NameList/GirlsNamesTab';
import BoysNamesScreen from './App/components/NameList/BoysNamesTab';
const MainStack = createStackNavigator();
const MainStackScreen = () => (
<MainStack.Navigator>
<MainStack.Screen
name="MainScreen"
component={MainScreen}
options={{ title: "Main Screen title" }}
/>
<MainStack.Screen
name="NamesList"
component={NamesList}
options={{ title: "NamesList Screen title" }}
/>
<MainStack.Screen
name="NameMeaning"
component={NameMeaning}
options={{ title: "NameMeaning Screen title" }}
/>
<MainStack.Screen
name="TabsScreen"
component={TabsScreen}
options={{ title: "TabsScreen Screen title" }}
/>
</MainStack.Navigator>
);
const Tabs = createMaterialTopTabNavigator();
const GirlNamesStack = createStackNavigator();
const BoysNamesStack = createStackNavigator();
const GirlNamesStackScreen = () => (
<GirlNamesStack.Navigator>
<GirlNamesStack.Screen name="GirlsNames" component={GirlNamesScreen} />
</GirlNamesStack.Navigator>
);
const BoysNamesStackScreen = () => (
<BoysNamesStack.Navigator>
<BoysNamesStack.Screen name="BoysNames" component={BoysNamesScreen} />
</BoysNamesStack.Navigator>
);
const TabsScreen = () => (
<Tabs.Navigator>
<Tabs.Screen name="BoysNames" component={BoysNamesStackScreen} />
<Tabs.Screen name="GirlsNames" component={GirlNamesStackScreen} />
</Tabs.Navigator>
);
const RootStack = createStackNavigator();
const RootStackScreen = () => (
<RootStack.Navigator headerMode="none">
<RootStack.Screen
name="Main"
component={MainStackScreen}
options={{
animationEnabled: false
}}
/>
</RootStack.Navigator>
);
export default () => {
return (
<NavigationContainer>
<RootStackScreen/>
</NavigationContainer>
);
};

react-native react-nagivation-drawer keeps opening by default on App startup

I'm sorry for the what might turn out to be a very stupid question, but for some time now I'm struggling with the following issue, but I'm new to react-native.
I create a react-native app in which I implement the react-navigation-drawer navigation precisely as in the example.
What happens is that whenever I open the App the drawer is opened. The same things happens when i copy and paste the example from here: https://reactnavigation.org/docs/en/drawer-based-navigation.html
This makes me think I'm missing something with the dependencies. I've upgraded all i could think of from the needed librabries. My CPU is not a good one so I'm using my Android phone for testing.
I also get the warning "componentWillMount has been renamed..." when i use the react-navigation-drawer.
If you could help guide me to some information that would be helpful!
Thank you all in advance!
Below is some code for an example:
import React from 'react';
import { FlatList, ActivityIndicator, Text, Header, Image, View, ScrollView, Alert, TouchableWithoutFeedback, TouchableOpacity, TouchableHighlight, StyleSheet } from 'react-native';
import {Button, Icon, ThemeProvider} from 'react-native-elements';
import {createAppContainer, DrawerNavigator, withNavigation} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import {createDrawerNavigator, DrawerActions, DrawerLayoutAndroid} from 'react-navigation-drawer';
.....
const Screen1PageScreenStack = createStackNavigator({
Screen1Page: {
screen: Screen1Page,
}
},{
navigationOptions: ({ navigation }) => ({
initialRouteName: 'Screen1Page',
headerMode: 'screen',
drawerLabel: 'HOME',
drawerBackgroundColor: '#0000FF',
}
)
});
const Screen2PageScreenStack = createStackNavigator({
Screen2Page: {
screen: Screen2Page,
}
},{
navigationOptions: ({ navigation }) => ({
initialRouteName: 'Screen2Page',
headerMode: 'screen',
drawerLabel: 'Categories',
}
),
});
const appNavigator = createDrawerNavigator({
Screen1Page: {
name: 'Screen1PageScreenStack',
screen: Screen1PageScreenStack,
},
Screen2Page: {
name: 'Screen2PageScreenStack',
screen: Screen2PageScreenStack,
}
});
const MyDrawerStrugglesApp = createAppContainer(appNavigator);
export default MyDrawerStrugglesApp ;
You can try this code to keep your drawer hidden for required screen :
const Nav = createDrawerNavigator(
{
Home: {
screen: AppLogin,
navigationOptions:{
drawerLockMode: 'locked-closed',
drawerLabel: <Hidden />
},
},
}
);
Your Hidden class should be as follows :
class Hidden extends React.Component {
render() {
return null;
}
}
You can change the drawerLockMode value to keep the drawer opened or closed - Refer here for different values.
Also you can refer this SO answer here for avoiding the componentWillMount deprecation error. Hope this helps !
With react-navigation V5 you can pass the openByDefualt prop
<Drawer.Navigator
initialRouteName="Home"
openByDefault>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
With react-navigation v6 all you need to do is pass defaultStatus="closed" prop directly to Drawer.Navigator. The app will always load with the drawer closed.

Can I add a button to my webview for additional functionality?

I am designing a mobile app to work with a site we already have up and running. There are a few things we would like to take advantage of on the phone, however. For example, using the camera to upload photographs to the site.
Currently, I have this code
export default class App extends Component<Props> {
render() {
return (
<WebView
source={{uri: "https://example.com"}}
/>
);
}
}
Is there some way to add a button that lets users open a menu of options that exists on the app alone (and separate from the site in the webview).
I'v tried something like
export default class App extends Component<Props> {
render() {
return (
<View>
<Text>Test</Text>
<WebView
source={{uri: "https://example.com"}}
/>
</View>
);
}
}
just as a test to see if I can add other elements outside the webview, but my app never loads (I just see a blank white screen) when I try this.
The reason that Test and WewbView won't show up in your example code it's because View doesn't have a defined height, you can use flex:1 to give it the entire screen.
See this working sample:
https://snack.expo.io/#cgomezmendez/vengeful-tortillas
import * as React from 'react';
import { Text, View, StyleSheet, WebView } from 'react-native';
import { Constants } from 'expo';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Test</Text>
<WebView
source={{uri: "https://google.com"}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
You might have a look at this: react-native-webview-bridge

Building a notification from a modal in React Navigation

I am attempting to build a notification service I can use within React Navigation; how far I have gotten in this:
Now this is a modal, that the card element has been hidden and then the view style has been filled into only 15% at the top of the element, and the element will react if you click out of the white area of the notification.
Here is the code for the NotificationModal:
import React from 'react';
import { View, TouchableHighlight,TouchableWithoutFeedback } from 'react-native';
import { Text } from 'react-native-elements';
export default class NotificationModal extends React.Component {
static navigationOptions = ({ navigation }) => {
const title = navigation.getParam('title','No item found...');
return {
title: title
};
};
constructor(props) {
super(props);
}
componentDidMount() {
console.log(this.props);
}
render() {
const { navigation } = this.props;
let title = navigation.getParam('title', '');
return (
<TouchableWithoutFeedback>
<View style={{ flex: 1 ,flexDirection: 'column', justifyContent: 'flex-start'}}>
<View style={{ height: "15%" ,width: '100%', backgroundColor:"#fff", justifyContent:"center"}}>
<Text style={{fontSize:25}}>{title}xd</Text>
</View>
<TouchableHighlight onPress={() => { this.props.navigation.goBack(); }} style={{backgroundColor: "rgba(0,0,0,0)"}}>
<View style={{ height: "85%" ,width: '100%', backgroundColor: "rgba(0,0,0,0)", justifyContent:"center"}}>
<View>
</View>
</View>
</TouchableHighlight>
</View>
</TouchableWithoutFeedback>
);
}
}
At at my root navigation stack it looks like this:
export default RootStack = createStackNavigator(
{
Main: {
screen: MainStack,
},
QuickStockModal: {
screen: StockModal,
},
NotificationModal: {
screen: NotificationModal,
}
},
{
mode: 'modal',
headerMode: 'none',
cardStyle:{
backgroundColor:"transparent",
opacity:0.99
}
}
);
Finally I call this pseudo notification modal like any other navigation instance:
this.props.navigation.navigate('NotificationModal', {
title: 'test'
});
Problems with this
It wont just act as a quick update, it will overtake the touch area, I just wish to let the user know things like 'search results empty' or 'barcode invalid' etc, without hijacking the touch. (But being able to touch buttons of the notification within the white area thats visible)
When you press the outside area to dismiss it, the 'dismiss area' turns dark as it disappears, this looks bad, I am hoping to change the animation to simply push up instead of down and hopefully avoid this
this is a messy way to do notifications but other manners will complicate my current app design too much (Using Redux for instance, will be alot of work for simply trying to add in-app notifications)
In-app notification libs arent customizable enough and also dont even work properly sadly

Categories

Resources