React Navigation Scroll View like transition? - reactjs

I want to do something like:
Is this possible?
The default is like this:
Thanks.

I believe the two effects you are showing are the same. The only difference is that the desired one has navigation bar at the top which has an animation that looks like the bar is standing still while the text on it changed. It you add a navigation bar to your example you would see that they are the same.
Update
The following code achieve the visual effect. Note that I used a TabNavigator instead of a StackNavigator:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import { StackNavigator, TabNavigator } from 'react-navigation';
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
const InitialScreen = (props) =>
<View style={[styles.container, { backgroundColor: 'gray' }]}>
<TouchableOpacity onPress={() => props.navigation.navigate('Final')}>
<Text>Initial Screen</Text>
</TouchableOpacity>
</View>;
const FinalScreen = (props) =>
<View style={[styles.container, { backgroundColor: 'pink' }]}>
<TouchableOpacity onPress={() => props.navigation.navigate('Initial')}>
<Text>Final Screen</Text>
</TouchableOpacity>
</View>;
const App = TabNavigator({
Initial: { screen: InitialScreen },
Final: { screen: FinalScreen },
}, {
animationEnabled: true,
navigationOptions: {
tabBarVisible: false,
},
});
AppRegistry.registerComponent('testTransition', () => App);
Put it in your index.ios.js to try it out and play around with it :P

Related

navigation.navigate is not a function. (In 'navigation.navigate("HomeScreen")', 'navigation.navigate' is undefined)

I m very new in react native and I m getting this error. Please help!
navigation.navigate is not a function. (In 'navigation.navigate("HomeScreen")', 'navigation.navigate' is undefined)
import { View, Text,Button,StyleSheet, TouchableOpacity } from 'react-native'
import React, {useState} from 'react'
import { NavigationContainer,CommonActions, useNavigation } from '#react-navigation/native';
const GetOtpButton = (navigation) => {
return (
<View >
<TouchableOpacity style = {styles.button} onPress={() => navigation.navigate("HomeScreen") } >
<Text style = {styles.text}>Log in</Text>
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
button: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: "white",
width: "100%",
height: 50,
borderColor: "#E13C72",
backgroundColor: "#E13C72",
borderWidth: 0.1,
borderRadius: 80,
// marginBottom: 40,
// marginVertical: 5,
// marginTop: 10,
},
text: {
justifyContent: 'center',
textAlign: 'center',
color: "white",
fontWeight: 'bold'
}
});
export default GetOtpButton
---------------------App.js------------------
import react from "react";
import { StatusBar } from "expo-status-bar";
import { SafeAreaView, StyleSheet, Text, View, Dimensions } from "react-native";
import SigninScreen from "./src/SigninScreen/SigninScreen";
import HomeScreen from "./src/HomeScreen/HomeScreen";
import { NavigationContainer, StackActions } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="SigninScreen" options={{headerShown: false}}>
<Stack.Screen name = 'SigninScreen' component={SigninScreen} options={{headerShown: false}}/>
<Stack.Screen name = 'HomeScreen' component={HomeScreen} options={{headerShown: false}}/>
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
root: {},
container: {
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#FFFFFF",
},
});
The component GetOptButton is not defined as a screen in the navigator, thus the navigation object will not be passed to it automatically by the navigation framework. Thus, you have multiple choices here.
Define it as a screen inside the navigator
<Stack.Screen name = 'GetOpt' component={GetOptButton} />
The framework will now pass the navigation object to the GetOptButton component. You can access it as follows.
const GetOtpButton = ({navigation}) => { ... }
Now, since GetOptButton seems to be a component rather than a screen to which you will navigate, it might not make much sense to define it inside the navigator.
Pass the navigation object from a screen which is defined in the navigator that uses the GetOptButton component
// this works, since `Homescreen` is defined as a screen in your navigator
const HomeScreen = ({navigation}) => {
return (
<GetOptButton navigation={navigation} />
)
}
Destructure the navigation object inside GetOptButton as shown above.
Use the useNavigation hook
For some components it might not make sense to pass the navigation object from its parent, e.g. if the component is deeply nested. For this cases you can use the useNavigation hook.
const GetOptButton = () => {
const navigation = useNavigation()
}
You are not showing how GetOtpButton is used but guessing that navigation is passed as prop to GetOtpButton you need to get to navigation like this
const GetOtpButton = ({navigation}) => {
return (
<View >
<TouchableOpacity style = {styles.button} onPress={() => navigation.navigate("HomeScreen") } >
<Text style = {styles.text}>Log in</Text>
</TouchableOpacity>
</View>
)
}
See that the difference is that navigation is surrounded by curly brackets, so later you get the parameter navigation inside the props

Switch navigator does not works in React Native

I've asked a question already, and modified as much as I can, but still in trouble.
Combined all children Screen js files into App.js
When I compile and run, App shows LoginScreen.js, not LoadingScreen.js.
Also, onPress={this.props.navigation.navigate('Loading')} does not works. If I press the button, it shows nothing.
What am I still missing?
import React from 'react'
import { StyleSheet, Platform, Image, Text, View, TextInput, Button, ActivityIndicator } from 'react-native'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';
class LoadingScreen extends React.Component {
render() {
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={this.props.navigation.navigate('Login')} />
</View>
)
}
}
class LoginScreen extends React.Component {
state = { email: '', password: '' }
render() {
return (
<View style={styles.logincontainer}>
<Button
title='Sign in' onPress={this.props.navigation.navigate('Loading')}
/>
<Button
title='Sign Up'
/>
</View>
)
}
}
const styles = StyleSheet.create({
loadingcontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
logincontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logintextInput: {
height: 40,
width: '90%',
borderColor: 'gray',
borderWidth: 1,
marginTop: 8
},
})
const App = createSwitchNavigator(
{
Loading: {
screen: LoadingScreen,
},
Login: {
screen: LoginScreen,
},
}
);
export default createAppContainer(App);
Thank you for your help.
For just navigation, you can use a stack navigator. The switch navigator used for conditional rendering of two different stacks. Anyways you can set loading as the first screen buy setting initialRouteName to loading. Here is an example
createSwitchNavigator(
{
LimitedAccess: {
screen: Trial,
},
AppScreens: {
screen: AppScreens,
},
AuthScreens: {
screen: AuthScreens,
},
},
{
initialRouteName: signedIn ? 'AppScreens' : 'AuthScreens',
},
),
);
Note: Here signedIn is a conditional operator which decides the rendering of stacks.
The way your props are currently defined causes them to be instantly executed.
The onPress prop is instantly executed.
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={this.props.navigation.navigate('Login')} />
</View>
)
You should instead attach a function to onPress that can be executed when the button is pressed.
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={() => this.props.navigation.navigate('Login')} />
</View>
)
Your onPress-calls are running instantly, which causes your problems.
Change to:
import React from 'react'
import { StyleSheet, Platform, Image, Text, View, TextInput, Button, ActivityIndicator } from 'react-native'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';
class LoadingScreen extends React.Component {
render() {
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={() => this.props.navigation.navigate('Login')} />
</View>
)
}
}
class LoginScreen extends React.Component {
state = { email: '', password: '' }
render() {
return (
<View style={styles.logincontainer}>
<Button
title='Sign in' onPress={() => this.props.navigation.navigate('Loading')}
/>
<Button
title='Sign Up'
/>
</View>
)
}
}
const styles = StyleSheet.create({
loadingcontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
logincontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logintextInput: {
height: 40,
width: '90%',
borderColor: 'gray',
borderWidth: 1,
marginTop: 8
},
})
const App = createSwitchNavigator(
{
Loading: {
screen: LoadingScreen,
},
Login: {
screen: LoginScreen,
},
}
);
export default createAppContainer(App);

React native createDrawerNavigator is not working

Could you please help me on this small issue.
I am very very new to React native and here i am training in learn react navigation. My problem is Drawer navigator is not working when i try to swap from left to right. But bottom navigator is working. Any idea whats wrong with this please.
Also: if you can please send me a good sample to learn this area.
I have some samples, but most of the samples are outdated.
MyCode:
import React from 'react';
import {TouchableOpacity, View, Text, Image} from 'react-native';
import {createAppContainer, createSwitchNavigator} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import {createBottomTabNavigator} from 'react-navigation-tabs';
import {createDrawerNavigator} from 'react-navigation-drawer';
import HomeScreen2 from '../screens/HomeScreen2';
import HomeScreen from '../screens/HomeScreen';
import Setup from '../screens/Setup';
const HomeStack = createStackNavigator(
{
//Defination of Navigaton from home screen
Home: { screen: HomeScreen },
// Details: { screen: ProfileScreen },
},
{
defaultNavigationOptions: {
//Header customization of the perticular Screen
headerStyle: {
backgroundColor: '#42f44b',
},
headerTintColor: '#FFFFFF',
title: 'Home',
//Header title
},
}
);
const SettingsStack = createStackNavigator(
{
//Defination of Navigaton from setting screen
Settings: { screen: Setup },
},
{
defaultNavigationOptions: {
//Header customization of the perticular Screen
headerStyle: {
backgroundColor: '#42f44b',
},
headerTintColor: '#FFFFFF',
title: 'Settings',
//Header title
},
}
);
const TabMain = createBottomTabNavigator(
{
TAB1: HomeStack,
TAB2: SettingsStack,
},
{
initialRouteName: 'TAB1',
}
)
const DrawHomeView = createStackNavigator({
HomeV: {screen: HomeScreen2}},
{
headerMode: 'float',
navigationOptions: ({navigation}) => ({
headerStyle: {
backgroundColor: 'rgb(255,45,85)',
paddingLeft: 10,
paddingRight: 10
},
title: 'Map View',
headerTintColor: 'white',
headerLeft: <View>
<TouchableOpacity
onPress={() => {
if (navigation.state.isDrawerOpen === false) {
navigation.dispatch(DrawerActions.openDrawer());
} else {
navigation.dispatch(DrawerActions.closeDrawer());
}
}}>
<Text>Menu</Text>
</TouchableOpacity>
</View>
})
});
const DrawSettingsView = createStackNavigator({
SettingsV: {screen: Setup}},
{
headerMode: 'float',
navigationOptions: ({navigation}) => ({
headerStyle: {
backgroundColor: 'rgb(255,45,85)',
paddingLeft: 10,
paddingRight: 10
},
title: 'Map View',
headerTintColor: 'white',
headerLeft: <View>
<TouchableOpacity
onPress={() => {
if (navigation.state.isDrawerOpen === false) {
navigation.dispatch(DrawerActions.openDrawer());
} else {
navigation.dispatch(DrawerActions.closeDrawer());
}
}}>
<Text>Menu</Text>
</TouchableOpacity>
</View>
})
});
const TabMain2 = createDrawerNavigator(
{
TAB3: DrawHomeView,
TAB4: DrawSettingsView,
},
{
initialRouteName: 'TAB3',
}
)
export default createAppContainer(createSwitchNavigator(
{
Sub1: TabMain,
Sub2: TabMain2,
},
{
initialRouteName: 'Sub2',
}
));
Okay. After some dabbling with your code and the docs : https://reactnavigation.org/docs/nesting-navigators/
and please read the docs and try their examples as they are excellent descriptive and available for real time execution on snack.
For the second part of the question, i put together an example for you:
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
//Import necessary components
//Create Screens, Dummy screens in this case.
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
function Feed ({ navigation, route }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize: 40}}>Feed </Text>
</View>
);}
function Home ({ navigation, route }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize: 40}}> Home </Text>
</View>
);}
// Here is your questions answer, just create a Bottom Navigator
// and a Drawer Navigator and nest them in each other after declaring your
// screens.
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
function HomeScreen({ navigation }) {
return (
<Tab.Navigator>
//Put your Tab screens here.
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Feed" component={Feed} />
</Tab.Navigator>
);
}
export default function App() {
return (
// For the main export create a navigation container and declare the
// Drawer Navigator inside the main navigation container, then use that to
// To Access your Tab navigator "HomeScreen" and put whatever else you
// Want in your Drawer Navigator.
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Explanation: You are only allowed to nest navigators within each other and not within the main navigation container.
This code has been tested using expo-cli 3.18.4

How to change background color of drawer in react-navigation fully

How can I change Background Color of the drawer fully? I don't need to change drawer items need to change the background color of the drawer fully. By default, it's white while I need to make it Green. Is there any demo example?
Old question, but this may help people that are looking for this solution. On createDrawerNavigator you have a drawerConfig property called drawerBackgroundColor.
Example:
import React from 'react';
import { createDrawerNavigator } from 'react-navigation';
import Home from '../screens/Home';
import Screen2 from '../screens/Screen2';
export default createDrawerNavigator({
Home,
Screen2
}, {
drawerPosition: 'left',
drawerBackgroundColor: '#0000FF',
});
You can read more about it, on React Navigation documentation: https://reactnavigation.org/docs/en/drawer-navigator.html
This Current example can help you , This the DrawerNavigtor using DrawerContent , Need to change the style of DrawerContent
const Main = DrawerNavigator({
home: { screen: HomePage },
}, {
drawerWidth: 250,
drawerPosition: 'right',
contentComponent: props => <DrawerContent {...props} />,
});
export default Main;
You can Change the style by using the this code below
class DrawerContent extends Component {
render() {
return (
<ScrollView style={styles.container}>
<View style={{ flex: 1 }}>
<Button transparent info onPress={() => { this.handlechange(); }}>
<Text style={{ fontSize: 16 }}>Change Email</Text>
</Button>
</View>
</ScrollView>
);
}
}
const styles = {
container: {
flex: 1,
padding: 20,
backgroundColor: 'Green',
},
};
export default DrawerContent;
This can change the background color

How to add stateless component to a touchable component

I am trying to add a stateless component to my button.
const button = ({onButtonPress, buttonText}) => {
return (
<TouchableHighlight
onPress={() => onButtonPress()}>
<ButtonContent text={buttonText}/>
</TouchableHighlight>
)
};
and get this error:
Warning: Stateless function components cannot be given refs (See ref "childRef"
in StatelessComponent created by TouchableHighlight).
Attempts to access this ref will fail.
I have read up on the issue but I am still new to javascript and RN and have not found a solution. Any help would be appreciated.
full code:
GlossaryButtonContent:
import React from 'react';
import {
View,
Text,
Image,
StyleSheet
} from 'react-native';
import Colours from '../constants/Colours';
import {
arrowForwardDark,
starDarkFill
} from '../assets/icons';
type Props = {
text: string,
showFavButton?: boolean
}
export default ({text, showFavButton} : Props) => {
return (
<View style={styles.container}>
{showFavButton &&
<Image
style={styles.star}
source={starDarkFill}/>}
<Text style={[styles.text, showFavButton && styles.favButton]}>
{showFavButton ? 'Favourites' : text}
</Text>
<Image
style={styles.image}
source={arrowForwardDark}
opacity={showFavButton ? .5 : 1}/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'center'
},
favButton: {
marginLeft: 10,
color: Colours.darkTextHalf
},
text: {
flex: 1,
paddingTop: 5,
marginLeft: 20,
fontFamily: 'Bariol-Bold',
fontSize: 24,
color: Colours.darkText
},
image: {
marginRight: 20
},
star: {
marginLeft: 10
}
});
GlossaryButton:
import React from 'react';
import {
TouchableHighlight,
StyleSheet
} from 'react-native';
import Colours from '../constants/Colours';
import ShadowedBox from './ShadowedBox';
import GlossaryButtonContent from './GlossaryButtonContent';
type Props = {
buttonText: string,
onButtonPress: Function,
rowID: number,
sectionID?: string,
showFavButton?: boolean
}
export default ({buttonText, onButtonPress, rowID, sectionID, showFavButton} : Props) => {
return (
<ShadowedBox
style={styles.container}
backColor={showFavButton && Colours.yellow}>
<TouchableHighlight
style={styles.button}
underlayColor={Colours.green}
onPress={() => onButtonPress(rowID, sectionID)}>
<GlossaryButtonContent
text={buttonText}
showFavButton={showFavButton}/>
</TouchableHighlight>
</ShadowedBox>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
height: 60,
marginBottom: 10,
borderRadius: 5
},
button: {
flex: 1,
borderRadius: 5
}
});
Basically, Stateless components cannot have refs.
So, having a stateless component in the middle of the render tree will create a void in the ref chain, meaning you cannot access lower-down components.
So, the problem comes from trying to do this:
let Stateless = (props) => (
<div />
);
let Wrapper = React.createClass({
render() {
return <Stateless ref="stateeee" />
}
});
TouchableHighlight needs to give a ref to its child. And this triggers that warning.
Answer:
You can't actually make a stateless component a child of TouchableHighlight
Solution:
Use createClass or class to create the child of TouchableHighlight, that is GlossaryButtonContent.
See this github issue for more info and this one

Resources