React-native header title image is cut off, why? - react-native

So I'm working on a react-native application and I am using react-navigation for my navigation, using an image in the headerTitle in the screen options works however the image is cut off. I've tried messing with the height/width of the image, wondered if it was a padding issue with the header yet still nothing. Any ideas why?
Here is the component
import React from "react";
import { View, Image, StyleSheet } from "react-native";
function HeaderLogo(props) {
return(
<Image style={styles.logoStyles} source={require("../../assets/images/svg/LogoNoTxt.png")}/>
);
};
const styles = StyleSheet.create({
logoStyles: {
height: 40,
width: 40,
},
});
export default HeaderLogo
Here is the stack navigator
import React from "react";
import { createStackNavigator } from '#react-navigation/stack';
//Components
import HeaderLogo from "../../components/images/HeaderLogo";
//TopTab
import HomeTopTabNavigator from "../topTab/HomeTopTabNavigator";
//Screens
import AddTasks from "../../screens/home/AddTasks";
//Initialize vars
const Stack = createStackNavigator();
function HomeStackNavigator() {
return(
<Stack.Navigator screenOptions={defaultOptions}>
<Stack.Screen name="Home" component={HomeTopTabNavigator}/>
<Stack.Screen name="AddTasks" component={AddTasks}/>
</Stack.Navigator>
);
};
//Options
const defaultOptions = {
headerStyle: {
elevation: 0,
shadowColor: "transparent",
},
//headerTitleAlign: "center",
headerTitle: (
<HeaderLogo />
),
headerTitleAlign: "center",
};
export default HomeStackNavigator;
Image of Logo on the header (cut off)

Just wrapped the component in a function, and it rendered properly.

For posterity:
headerTitle: () => <HeaderLogo />

Related

Delayed rendering of parent Drawer header inside Bottom Tab

I have BottomTab navigator with 2 screens Home and Activity, nested inside a Drawer Navigator. When I switch from one screen to second one using BottomTab, my header of Drawer Navigator hides with flickering effect and same thing happens again when I show it up on previous screen. I am handling headerShown:true and headerShown:false in listeners prop of Tab.Screen using focus and blur of that screen.
It seems like header is rendering after rendering of components below it. This header showing and hiding has more delay if I have multiple components inside both screens.
Snack repo is attached.
https://snack.expo.dev/#a2nineu/bottomtab-inside-drawer
I suggest you use Interaction Manager
As react-native is single threaded, JS gets blocked while running animation which can cause UI to lag and jitter.
Attaching code with changes
import 'react-native-gesture-handler';
import * as React from 'react';
import {
Text,
View,
StyleSheet,
Image,
InteractionManager,
} from 'react-native';
import Constants from 'expo-constants';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
const Drawer = createDrawerNavigator();
const Tab = createMaterialBottomTabNavigator();
const Home = (props) => {
React.useEffect(() => {
const interactionPromise = InteractionManager.runAfterInteractions(() =>
setShowContent(true)
);
return () => interactionPromise.cancel();
}, []);
const [showContent, setShowContent] = React.useState(false);
return showContent ? (
<View>
<Text>Home</Text>
<Image
source={{
uri: 'https://images.unsplash.com/photo-1596265371388-43edbaadab94?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80',
}}
style={{ height: 500, width: 500 }}
resizeMode={'cover'}></Image>
</View>
) : null;
};
const Activity = () => {
return <Text>Activity</Text>;
};
const BottomTab = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen
name="Activity"
component={Activity}
listeners={({ navigation, route }) => ({
focus: () => {
navigation.getParent().setOptions({
headerShown: false,
});
},
blur: () => {
navigation.getParent().setOptions({
headerShown: true,
});
},
})}
/>
</Tab.Navigator>
);
};
export default function App() {
return (
<View style={styles.container}>
<NavigationContainer>
<Drawer.Navigator screenOptions={{ headerMode: 'float' }}>
<Drawer.Screen
options={{ headerStyle: { height: 100 } }}
name="BottomTab"
component={BottomTab}
/>
</Drawer.Navigator>
</NavigationContainer>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});

How can I change React Native iOS simulator DarkMode?

I wrote code and did shift + command + a in iOS simulator but I could see mode is not changed from console.log what is the problem?
import {createBottomTabNavigator} from "#react-navigation/bottom-tabs";
import { useColorScheme } from "react-native-web";
import Movies from "../screens/Movies";
import Search from "../screens/Search";
import Tv from "../screens/Tv";
const Tab = createBottomTabNavigator();
const Tabs = () => {
const colorScheme = useColorScheme();
console.log(colorScheme);
return(
<Tab.Navigator >
<Tab.Screen name="Movies" component={Movies} options={{
}}/>
<Tab.Screen name="Tv" component={Tv}/>
<Tab.Screen name="Search" component={Search}/>
</Tab.Navigator>
);
}
export default Tabs;
first :
import * as RN from "react-native";
import {
DarkTheme,
DefaultTheme,
NavigationContainer,
} from "#react-navigation/native";
in App.js :
let cs = RN.useColorScheme();
let isDark = cs === "dark";
let theme = isDark ? DarkTheme : DefaultTheme; // or your custom theme [1]
...
...
<NavigationContainer theme={theme}>
<Tabs />
</NavigationContainer>
...
[1] : react-navigation theme
and if you want use react-navigation theme object in functional components :
import { useTheme } from "#react-navigation/native";
and after defining your function component :
let { colors, dark } = useTheme();
and in JSX :
...
<View
style={{
width: 100,
height: 175,
margin: 10,
alignItems: "center",
borderWidth: 1,
backgroundColor: colors.primary,
borderRadius: 10,
justifyContent: "space-evenly",
}}
/>
...
The getColorScheme() hook will always return light when debugging with Chrome. Disable debugging to return dark.
Example to debug
const colorScheme = useColorScheme();
useEffect(() => {
if (colorScheme) {
Alert.alert(colorScheme)
}
}, [colorScheme])

I want to move the screen with a button in React Native

I want to go to another screen by pressing the image button on the screen, but I don't know how. I am a complete beginner.
How can I go to the next page?
import React, { Component } from 'react'
import { StyleSheet, Text, View, TouchableOpacity,Image,Alert } from 'react-native';
import {} from 'react-navigation';
const ButtonScreen = props => {
const content = (
<View style= {[styles.button]}>
<Image source={require('../assets/icon/룰렛.png')} style={{
transform: [{scale: 0.37}],
}}
/>
</View>
)
return (
<TouchableOpacity onPress={() => {
Alert.alert('빨리');
}}
>{content}</TouchableOpacity>
)
}
const styles = StyleSheet.create ({
button: {
top: 60,
flexDirection: 'row',
alignItems: 'center',
height: '30%',
width: '100%',
},
})
export default ButtonScreen;
for navigation in react-native there are various libraries. react-navigation, react-native-router-flux, react-native-navigation(wix) are the ways you can use for navigation.
react-navigation is the famous one that currently has V5.x following by thorough documentation. It uses JavaScript codes for navigation and I assume you installed this library.
the react-native-router-flux use react-navigation V4.x and it really looks like react-router-dom in React-js. However I strongly suggest to not using that due to problems regarding performance.
react-native-navigation(wix) has the highest performance because it uses native codes for navigation. however it has poor document and it is really difficult for beginners to use.
In order to use the current version of react-navigation the first step you need to do is the installation of requirement then you need to have separate file for defining your routes. Lets assume you have two screens. the file looks like the following code:
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Screen1 from 'the path of Screen1'
import Screen2 from ' the path of Screen2'
const Stack = createStackNavigator();
function Navigation() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Screen1" component={Screen1} />
<Stack.Screen name="Screen2" component={Screen2} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default Navigation
then you need to import this file on your index file.
import Navigation from "the path of Navigation";
AppRegistry.registerComponent(appName, () => Navigation);
if you are at ButtonScreen and you want to go on Screen2 you need the following code:
import React, { Component } from 'react'
import { StyleSheet, Text, View, TouchableOpacity,Image,Alert } from 'react-native';
const ButtonScreen = props => {
const content = (
<View style= {[styles.button]}>
<Image source={require('../assets/icon/룰렛.png')} style={{
transform: [{scale: 0.37}],
}}
/>
</View>
)
return (
<TouchableOpacity onPress={() => props.navigation.navigate("Screen2")}
>{content}</TouchableOpacity>
)
}
const styles = StyleSheet.create ({
button: {
top: 60,
flexDirection: 'row',
alignItems: 'center',
height: '30%',
width: '100%',
},
})
export default ButtonScreen;
this is the easiest way to navigate and I recommend you to read the document

Navigation issue in Reat Naivgation, React Native

I am using react-navigation 5 in my mobile app and I am stuck in implementing a log-off feature.
The scenario is I have a stack navigator and a bottom tab navigator in my app. The app starts with the stack navigator (Login feature and Reset Password Feature) and on login goes to the dashboard Page which is from the bottom tab navigator. Now on the Dashboard page, I am implementing a logout feature which when clicked should take me to the login page (part of stack navigator), and no matter what I try it keeps giving me errors like these
The action 'RESET' with payload {"index":0,"routes":[{"name":"AuthNavigator"}]} was not handled by any navigator.
Here are my code snippets right from start
Component Called from App.js
import React, { useState, useEffect, useContext } from "react";
import { ActivityIndicator } from "react-native";
import AsyncStorage from '#react-native-async-storage/async-storage';
import { Center } from "../../components/Center";
import { AuthContext } from "../authentication/AuthProvider";
import { NavigationContainer } from "#react-navigation/native";
import { AuthNavigator } from "./AuthNavigator";
import { MainTabNavigator } from "./MainTabNavigator";
export default function App() {
const { user, login } = useContext(AuthContext);
const [loading, setLoading] = useState(true);
useEffect(() => {
// check if the user is logged in or not
//AsyncStorage.removeItem("user") //- uncomment this and refresh emulator to start from login screen
AsyncStorage.getItem("user")
.then(userString => {
if (userString) {
login();
}
setLoading(false);
})
.catch(err => {
console.log(err);
});
}, []);
if (loading) {
return (
<Center>
<ActivityIndicator size="large" />
</Center>
);
}
return (
<NavigationContainer>
{user ? <MainTabNavigator /> : <AuthNavigator />}
</NavigationContainer>
);
}
AuthNavigator.js
import React from "react";
import { createStackNavigator } from '#react-navigation/stack';
import Login from '../authentication/Login';
import ResetPassword from '../authentication/ResetPassword';
import { MainTabNavigator } from "./MainTabNavigator";
const Stack = createStackNavigator();
export const AuthNavigator = () => {
return (
<Stack.Navigator initialRouteName="Login">
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="ResetPassword" options={{headerTitle: "Reset Password"}} component={ResetPassword} />
</Stack.Navigator>
);
}
MainTabNavigator.js
import * as React from 'react';
import { Text, View, Image, StyleSheet, Platform } from 'react-native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import DashboardView from '../dashboard/DashboardView';
import Search from '../searchLoan/Search';
import { colors } from '../../styles';
const iconHome = require('../../../assets/images/tabbar/home.png');
const iconGrids = require('../../../assets/images/tabbar/grids.png');
const searchIcon = require('../../../assets/images/pages/search_24px.png');
const Tab = createBottomTabNavigator();
const tabData = [
{
name: 'Dashboard',
component: DashboardView,
icon: iconHome,
},
{
name: 'Search',
component: Search,
icon: searchIcon,
},
];
export const MainTabNavigator = () => {
return (
<Tab.Navigator tabBarOptions={{ style: { height: Platform.OS === 'ios' ? 90 : 50 } }}>
{tabData.map((item, idx) => (
<Tab.Screen
key={`tab_item${idx + 1}`}
name={item.name}
component={item.component}
options={{
tabBarIcon: ({ focused }) => (
<View style={styles.tabBarItemContainer}>
<Image
resizeMode="contain"
source={item.icon}
style={[styles.tabBarIcon, focused && styles.tabBarIconFocused]}
/>
</View>
),
tabBarLabel: ({ focused }) => <Text style={{ fontSize: 12, color: focused ? colors.primary : colors.gray }}>{item.name}</Text>,
title: item.name,
}}
/>
))}
</Tab.Navigator>
);
};
const styles = StyleSheet.create({
tabBarItemContainer: {
alignItems: 'center',
justifyContent: 'center',
borderBottomWidth: 2,
borderBottomColor: colors.white,
paddingHorizontal: 10,
bottom: Platform.OS === 'ios' ? -5 : 0,
},
tabBarIcon: {
width: 23,
height: 23,
},
tabBarIconFocused: {
tintColor: colors.primary,
},
});
DashboardView.js
import React , {useContext }from 'react';
import { StyleSheet, View, TouchableOpacity, Text } from 'react-native';
import {Header} from 'react-native-elements';
import AntIcon from "react-native-vector-icons/AntDesign";
import { colors, fonts } from '../../styles';
import AmountDetails from './AmountDetails';
import DashboardFields from './DashboardFields';
import { AuthContext } from "../authentication/AuthProvider";
import { CommonActions } from "#react-navigation/native";
export default function DashboardView(props) {
const appLogOut = () => {
const { logout } = useContext(AuthContext);
console.log('props', props)
if(logout){
// console.log("Navigation Object", navigation)
props.navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [{ name: "AuthNavigator" }],
}));
}
}
return (
<View style={styles.container}>
<Header containerStyle = {{backgroundColor: colors.primary}}
centerComponent={{ text: 'Dashboard', style: { color: colors.white, backgroundColor: colors.primary } }}
rightComponent = <TouchableOpacity onPress={appLogOut()}><AntIcon name="logout" color="white" size={25}/></TouchableOpacity>
/>
<View style={styles.container}>
<View>
<AmountDetails />
</View>
<View style={styles.dashboardFields}>
<DashboardFields />
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.gray,
},
dashboardFields: {
marginTop: 20,
},
});
You should try calling the login screen directly, not the whole stack.
CommonActions.reset({
index: 0,
routes: [{ name: "Login" }],
}));
As the other answer said, you have incorrect route name (AuthNavigator).
However, you're conditionally defining screens based on if the user is logged in. You don't need to do anything extra when logging out. Conditionally defining screens means React Navigation can automatically handle which screen to show when the conditional changes.
So you need to remove the code which does reset.
From the docs:
It's important to note that when using such a setup, you don't need to manually navigate to the Home screen by calling navigation.navigate('Home') or any other method. React Navigation will automatically navigate to the correct screen when isSigned in changes - Home screen when isSignedIn becomes true, and to SignIn screen when isSignedIn becomes false. You'll get an error if you attempt to navigate manually.
More details: https://reactnavigation.org/docs/auth-flow/

Is it possible using gradient color for android status bar with react-native?

I am trying to set a gradient color for android status bar using react-native. But setBackgroundColor is taking color string.
Is it possible to use gradient color for status bar color?
You can use translucent={true} and backgroundColor={'transparent'} properties with StatusBar and wrap them with react-native-linear-gradient
like this:
<LinearGradient colors={["#79e3fe","#635df8","#42385D"]} style={{flex: 1}}>
<StatusBar translucent={true} backgroundColor={'transparent'} />
</LinearGradient >
You can tweak that.
In my case I use wix/react-native-navigation to navigate between screen in my application. So I use theses options for displaying my screens.
navigatorStyle: {
navBarHidden: true,
statusBarColor: 'transparent',
drawUnderStatusBar: true
},
An after you need to import react-native-linear-gradient to tweak your status bar. (create a component and add it to your pages)
<View>
<LinearGradient colors={yourArrayOfColors} style={styles.header}/>
</View>
... //and in your style
header: {
height: (Platform.OS === 'ios' ? 20 : StatusBar.currentHeight),
}
That could do the trick !
It works out for me with the following steps.
Add React Navigation as root component for React Native.
Create a custom header and make a gradient background for it. react-native-linear-gradient is needed of course. The following code demonstrates how to do it.
// #flow
import React from "react";
import { View, Platform, StatusBar } from "react-native";
import { createStackNavigator, createAppContainer } from "react-navigation";
import { Header, StackViewTransitionConfigs } from "react-navigation";
import LinearGradient from "react-native-linear-gradient";
import MainScreen from "./MainScreen";
const GradientBackground = props => (
<LinearGradient
colors={["#FFD801", "#FF8040"]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
{...props}
/>
);
const AppNavigator = createStackNavigator(
{
MainScreen: { screen: MainScreen }
},
{
headerBackTitleVisible: false,
initialRouteName: "MainScreen",
defaultNavigationOptions: {
header: props => {
return (
// When StatusBar is translucent, the StatusBar will be offset up by "StatusBar.currentHeight" points.
// That's why the height of the Header is "Header.HEIGHT + StatusBar.currentHeight".
<View style={{ height: Header.HEIGHT + StatusBar.currentHeight }}>
<GradientBackground style={{ height: StatusBar.currentHeight }} />
<Header {...props} />
</View>
);
},
headerTintColor: "#FFF",
headerBackground: (
<GradientBackground style={{ height: Header.HEIGHT }} />
),
headerStyle: {
backgroundColor: "transparent"
}
},
headerLayoutPreset: "center"
}
);
const MainStack = createAppContainer(AppNavigator);
export default MainStack;
Add StatusBar to the root component and set StatusBar translucent.
// #flow
// #format
import React, { Component } from "react";
import { Button, TextInput, StyleSheet, StatusBar } from "react-native";
import { View, Text, FlatList } from "react-native";
import { NavigationScreenProp, NavigationState } from "react-navigation";
type Props = {
navigation: NavigationScreenProp<NavigationState>
};
/**
* 程序主页
* #export MainScreen
* #class MainScreen
* #extends {Component}
*/
export default class MainScreen extends Component<Props> {
static navigationOptions = {
headerTitle: "MainScreen"
};
render() {
const { navigation } = this.props;
return (
<View style={[styles.screenContainer]}>
<StatusBar
barStyle="light-content"
translucent={true}
backgroundColor="transparent"
/>
</View>
);
}
}
const styles = StyleSheet.create({
screenContainer: {
flex: 1
}
});
Enjoy!
If the description above is not clear to you, feel free to download the ReactNavigationGradientStatusbar Project and check it out.
1.add react-native-linear-gradient to your project
use this code :
import {View , StyleSheet,StatusBar} from 'react-native'
import LinearGradient from 'react-native-linear-gradient';
render(){
const StatusBarHeight = StatusBar.currentHeight
return(
<View>
<View style={{ height : StatusBarHeight , width : '100%' }}>
<LinearGradient
start={{x: 0.0, y: 0.5}}
end={{x: 0.5, y: 1.0}}
locations={[0,0.3,0.6]}
colors={['#4c669f', '#3b5998', '#192f6a']} style={style.Container}>
</LinearGradient>
</View>
</View>
)
}
and this :
const style = StyleSheet.create({
Container : {
flex : 1,
backgroundColor : '#2980b9',
justifyContent : 'center',
alignItems : 'center',
flexDirection : 'row'
}
})
As the documentation states at this point it only accepts a string, so no, you cannot. And, besides, I can't even come up with an app using a gradient on their status bar.
If the StatusBar would accept a component you could try using the Expo.io API to do so. Check https://docs.expo.io/versions/latest/sdk/linear-gradient.html if you are curious about it.