I'm a newbie in react-native. What I try to do is putting a drawer on the screen and open it with the "menu" button in the toolbar.
I know that I must use callback functions, I previously searched a lot of topics and related questions such as this one but I couldn't do it. Getting Almost crazy. Here's my code:
/**
* #flow
*/
const React = require('react');
const ReactNative = require('react-native');
const { View, Text, DrawerLayoutAndroid } = ReactNative;
class Profile extends React.Component<{}> {
static navigationOptions = {
title: 'Profile',
headerRight: <Text>Menu</Text>,
};
constructor() {
super();
this.openDrawer = this.openDrawer.bind(this);
}
openDrawer() {
this.ref.drawer.openDrawer();
}
render() {
const navigationView = (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<Text style={{ margin: 10, fontSize: 15, textAlign: 'left' }}>Im in the Drawer!</Text>
</View>
);
return (
<DrawerLayoutAndroid
drawerWidth={300}
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => navigationView}
ref={(_drawer) => {
this.drawer = _drawer;
}}
>
<View style={{ flex: 1, alignItems: 'center' }}>
<Text style={{ margin: 10, fontSize: 15, textAlign: 'right' }}>Hello</Text>
<Text
style={{ margin: 10, fontSize: 15, textAlign: 'right' }}
onPress={this.openDrawer()}
>
World!
</Text>
</View>
</DrawerLayoutAndroid>
);
}
}
export default Profile;
Every time I run the code, I get the "undefined is not an object".
Also, I don't know how to put openDrawer() inside the static navigationOptions.
Help is really appreciated!
Related
I am new to react native. I tried to change the background view on the container seems like it doesn't work. I attached the codes below.
Could anyone here tell me what is wrong with the code below?
const HomeScreen = () => {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: '#FF0000' }}>
<Text style={{
color: COLORS.Text,
marginLeft: 14,
marginTop: 16,
width: 100,
height: 20
}}>Hello world</Text>
</View>
</SafeAreaView>
);
Check the below code:
import React from 'react';
import {StyleSheet, Text, SafeAreaView } from 'react-native';
const App = () => {
return (
<SafeAreaView style={styles.container}>
<Text style={styles.text}>Page content</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor:'green'
},
text: {
fontSize: 25,
fontWeight: '500',
},
});
export default App;
For more information, you can explore SafeArea Documentation.
I'd like help regarding the test code in the expo-camera, I am using expo go and once I run the code, it gives me this error: TypeError: undefined is not an object (evaluating '_expoCamera.CameraType.back'), here is the documentation for the expo-camera: https://docs.expo.dev/versions/latest/sdk/camera/ , I am currently using expocamera 12.3.0 and have used navigation.navigate to navigate to this tab thanks ! and here is the code I directly copied from the site
import { Camera, CameraType } from 'expo-camera';
import { useState } from 'react';
import { Button, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
export default function App() {
const [type, setType] = useState(CameraType.back);
const [permission, requestPermission] = Camera.useCameraPermissions();
if (!permission) {
// Camera permissions are still loading
return <View />;
}
if (!permission.granted) {
// Camera permissions are not granted yet
return (
<View style={styles.container}>
<Text style={{ textAlign: 'center' }}>
We need your permission to show the camera
</Text>
<Button onPress={requestPermission} title="grant permission" />
</View>
);
}
function toggleCameraType() {
setType((current) => (
current === CameraType.back ? CameraType.front : CameraType.back
));
}
return (
<View style={styles.container}>
<Camera style={styles.camera} type={type}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.button}
onPress={toggleCameraType}>
<Text style={styles.text}>Flip Camera</Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
camera: {
flex: 1,
},
buttonContainer: {
flex: 1,
flexDirection: 'row',
backgroundColor: 'transparent',
margin: 64,
},
button: {
flex: 1,
alignSelf: 'flex-end',
alignItems: 'center',
},
text: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
},
});
Update: fixed it, just changed CameraType.back into Camera.Constants.Type.back, solved
I am making an app which has some buttons that play different sounds, and a stop button which stops all the sounds. However, it works only when the current sound playing stops, and does not play any other music. Is the function incorrect? Here is the code(the other buttons are written in the same way as the first button):
import React, { Component } from 'react';
import { Button, View, Text, Alert, TouchableOpacity } from 'react-native';
import {Audio} from "expo-av";
class Button1 extends React.Component {
playSound1 = async () => {
await Audio.Sound.createAsync(
{uri:"https://s1.yt.ninja/#download/23481-602b351bd79f3-10112020-252-320-file-10112020/mp3/lcVNSPXM2Nc/The%2BUntamed%2BOST%2B%257C%2B%25E9%2599%2588%25E6%2583%2585%25E4%25BB%25A4%2BMain%2BThemed%2BSong%25E3%2580%258A%25E6%2597%25A0%25E7%25BE%2581%2BWu%2BJi%25E3%2580%258B%25E2%2580%2594%25E2%2580%2594Xiao%2BZhan%2B%25E3%2580%2581Wang%2BYi%2BBo%2BDuet.mp3/9f05bbbdbd17b34a35bd40794186a567e755c50ee15ef6c77345bf1eaf7e8124-1"},
{shouldPlay:true}
)
}
render() {
return (
<TouchableOpacity style={{
backgroundColor : "#D1A5C9",
marginTop: 30,
marginLeft: 25,
width: 280,
height: 40,
alignItems: "center"
}}
onPress={this.playSound1}>
<Text style={{
color:"white",
fontSize: 30,
}}>Sound 1</Text>
</TouchableOpacity>
);
}
}
class StopButton extends React.Component{
render(){
return(
<TouchableOpacity style={{
backgroundColor : "black",
marginTop: 50,
marginLeft: 40,
width: 250,
height: 40,
alignItems: "center"
}}
onPress={() => {
Audio.setIsEnabledAsync(false)
}}>
<Text style={{
color:"white",
fontSize: 30,
}}>Stop Sound</Text>
</TouchableOpacity>
)
}
}
export default class App extends React.Component {
render() {
return (
<View>
<Button1/>
<Button2/>
<Button3/>
<Button4/>
<Button5/>
<StopButton/>
</View>
);
}
}
It will work, but only on your phone, not the simulators or the web options
But once you stop it, it wont start sound again ever, unless you add this
class SoundButton6 extends Component {
render() {
return (
<TouchableOpacity
style={{
backgroundColor: 'red',
marginLeft: 100,
borderWidth: 1,
borderColor: 'black',
alignItems: 'center',
justifyContent: 'center',
width: 200,
height: 100,
borderRadius: 100,
marginTop: 10,
}}
onPress={ () => {
Audio.setIsEnabledAsync(true);
}}>
<Text
style={{
fontWeight: 'bold',
fontSize: 35,
}}>
Resume
</Text>
</TouchableOpacity>
);
}
}
a resume button
Have a try by using the instance of the Audio.Sound to stop the audio.
For Ex:
const {
sound: soundObject,
status,
} = await Audio.Sound.createAsync(require('./assets/sounds/hello.mp3'), { shouldPlay: true });
and on the stop button action process the soundObject to stop the music:
onStop = async () => {
soundObject.stopAsync()
}
for more details check out the official docs from expo AV
https://docs.expo.io/versions/latest/sdk/audio/#audiosetaudiomodeasyncmode
I only started learning React native a week ago and here i'm trying to add animation to an app that loads films on search from the TMDB api, it works fine, but when trying the animation and after i press the search button it displays and error saying :
undefined is not an object (evaluating 'new _reactNativeReanimated.Animated.Value')
* components\FilmItem.js:18:17 in constructor
to be honest i searched on the net but i didn't find a similar problem so can anyone help ?
here's my code :
ps: the app works perfectly fine before trying the animation, i added the comments ' //>>> ' to the code i added for the animation, also i added some screens
search screen before validating a search
error screen
// Components/FilmItem.js
import React from "react";
import {
StyleSheet,
View,
Text,
Image,
TouchableOpacity,
Dimensions
} from "react-native";
import { getImageFromApi } from "../Api/TMDBApi";
import { Animated } from "react-native-reanimated";
class FilmItem extends React.Component {
//>>> added the constructor
constructor(props) {
super(props);
this.state = {
positionLeft: new Animated.Value(Dimensions.get("window").width)
};
}
//>>> added the componentDidMount()
componentDidMount() {
Animated.spring(
this.state.positionLeft, {
toValue: 0
}).start()
}
_displayFavoriteImage() {
if (this.props.isFilmFavorite) {
return (
<Image
source={require("../images/icons8-heart-filled.png")}
style={styles.favorite_image}
/>
);
}
}
render() {
const film = this.props.film;
const displayDetailForFilm = this.props.displayDetailForFilm;
return (
//>>> encapsulated the Touchable opacity inside a Animated.view with a style
<Animated.View style={{ left: this.state.positionLeft }}>
<TouchableOpacity
onPress={() => displayDetailForFilm(film.id)}
style={styles.main_container}
>
<Image
style={styles.image}
source={{ uri: getImageFromApi(film.poster_path) }}
/>
<View style={styles.content_container}>
<View style={styles.header_container}>
{this._displayFavoriteImage()}
<Text style={styles.title_text}>{film.title}</Text>
<Text style={styles.vote_text}>{film.vote_average}/10</Text>
</View>
<View style={styles.description_container}>
<Text style={styles.description_text} numberOfLines={6}>
{film.overview}
</Text>
{/* La propriété numberOfLines permet de couper un texte si celui-ci est trop long, il suffit de définir un nombre maximum de ligne */}
</View>
<View style={styles.date_container}>
<Text style={styles.date_text}>Sorti le {film.release_date}</Text>
</View>
</View>
</TouchableOpacity>
</Animated.View>
)
}
}
const styles = StyleSheet.create({
main_container: {
height: 190,
flexDirection: "row"
},
image: {
width: 120,
height: 180,
margin: 5,
backgroundColor: "gray"
},
content_container: {
flex: 1,
margin: 5
},
header_container: {
flex: 3,
flexDirection: "row"
},
title_text: {
fontWeight: "bold",
fontSize: 20,
flex: 1,
flexWrap: "wrap",
paddingRight: 5
},
vote_text: {
fontWeight: "bold",
fontSize: 16,
color: "#666666"
},
description_container: {
flex: 7
},
description_text: {
fontStyle: "italic",
color: "#666666"
},
date_container: {
flex: 1
},
date_text: {
textAlign: "right",
fontSize: 14
},
favorite_image: {
width: 25,
height: 25,
marginRight: 5
}
});
export default FilmItem;
I believe you are not importing your dependencies correctly - make sure you differentiate between default and named exports i.e.
import Animated, { Value } from 'react-native-reanimated'
then you would have e.g.
positionLeft: new Value(Dimensions.get("window").width)
See here for ES6 import syntax.
I have a disappearing header which I want to bring back into the view on a single tap anywhere on the screen. But if I am wrapping the entire <View> inside a <TouchableX> component the PanResponder stops working. Is there a hack around this?
You do not need to warp it with Touchable component.
Add next props to root View.
onResponderGrant - make View handle touch
onStartShouldSetResponder - make View handle start
To elaborate #Nicholas Chong advice, here is the example that works for me fine. You can use onTouchStart and onTouchEnd handlers on any View via props:
<View
onTouchStart={() => doSomething()}
style={{ width: '100%', height: '100%' }}
/>
More information
onResponderGrant not working for me, and I use onTouchEnd to trigger when tap the screen, this will work
This would be an example of a implementation with a onResponderGrant
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableOpacity
} from 'react-native';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
export default class App extends Component<{}> {
constructor() {
super();
this.startTouch = this.startTouch.bind(this);
this.stopTouch = this.stopTouch.bind(this);
this.onTouchE = this.onTouchE.bind(this);
}
startTouch() {
console.debug("You start so don't stop!??");
}
stopTouch() {
console.debug("Why you stop??");
}
onTouchE() {
console.debug("Touchable Opacity is working!!");
}
render() {
return (
<View style={styles.container}
onResponderGrant = { () => this.startTouch() }
onResponderRelease = { () => this.stopTouch() }
onStartShouldSetResponder = { (e) => {return true} }
>
<TouchableOpacity
onPress = { () => this.onTouchE() }
>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
</TouchableOpacity>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'cornflowerblue',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
I have included an example of using onResponderGrant and onStartShouldSetResponder inside of a View component.
(Thanks to your previously written answer, #Mr Br)
Definitions
import { Modal, Text, View } from "react-native";
import { useState } from "react";
const [visible, setVisible] = useState(false);
const dismissFunction = () => setVisible(false);
Presentation
<Modal visible={visible} transparent style={{ alignItems: "center", height: "100%", }} >
<View onResponderGrant={dismissFunction} onStartShouldSetResponder={dismissFunction} style={{ flex: 1, backgroundColor: "#1c1c1c75", flexDirection: "column", justifyContent: "flex-end", alignItems: "center" }} >
<View style={{ backgroundColor: "#1E2124", borderRadius: 30, justifyContent: "center", alignItems: "center", height: "30%", shadowColor: "#ffffff10", shadowOpacity: 10, shadowOffset: { width: 0, height: -5 }, width: "101%" }}>
<Text style={{ textAlign: "center", color: "#ffffff", fontSize: 24, marginLeft: "10%", marginRight: "10%", marginBottom: "10%", marginTop: "5%" }}>The message of your modal!</Text>
</View>
</View>
</Modal>
Don't forget to run setVisible(true) somewhere to get the modal to show!