Expo how to navigate between screens - react-native

So I've created three separate pages within the app and I've also added a Stack Navigator from React Native, but when I click on the button the app doesn't change page. As this is my first app in React any help would be massively appreciated!
This is what my Add.js looks like;
import React from "react";
import { YellowBox } from "react-native";
import { Font } from "expo";
import Timer from "./src/screens/Timer";
import Splash from "./src/screens/Splash";
import Main from "./src/screens/Main";
import { StackNavigator, DrawerNavigator } from "react-navigation";
const DrawerNavigation = DrawerNavigator({
Timer: {
screen: Timer
},
Splash: {
screen: Splash
},
Main: {
screen: Main
}
});
const StackNavigation = StackNavigator(
{
DrawerNavigation: {
screen: DrawerNavigation`enter code here`
},
Timer: {
screen: Timer
},
Splash: {
screen: Splash
},
Main: {
screen: Main
}
},
{
headerMode: "none"
}
);
export default class App extends React.Component {
constructor() {
super();
this.state = {
fontLoaded: false
};
YellowBox.ignoreWarnings([
"Warning: componentWillMount is deprecated",
"Warning: componentWillReceiveProps is deprecated",
"Warning: componentWillUpdate is deprecated"
]);
}
async componentDidMount() {
await Font.loadAsync({
Roboto: require("./src/assets/fonts/Arial.ttf")
/*FallbackFont*/`
});
this.setState({ fontLoaded: true });
console.warn("Fallback font is being used. Please check App.js
file.");
}
render() {
return this.state.fontLoaded ? <StackNavigation /> :
<Expo.AppLoading />;
}
}
And here is the Main.js;
import React, { Component } from "react";
import Button15 from "../symbols/button15";
import { Center } from "#builderx/utils";
import Button52 from "../symbols/button52";
import { View, StyleSheet, StatusBar, Image, ScrollView } from
"react-native";
export default class Main extends Component {
render() {
return (
<View style={styles.root}>
<StatusBar
barStyle="dark-content"
style={styles.statusBar}
animated={true}
/>
<Button15
style={styles.button15}
onPress={() => {
this.props.navigation.pop();
}}
/>
<ScrollView style={styles.scrollArea} horizontal={false} />
<Center horizontal>
<Image
source={require("../assets/DLLargeDarK.jpeg")}
style={styles.image}
/>
</Center>
<Center horizontal>
<View style={styles.rect3}>
<View style={styles.rect} />
<Center horizontal>
<Button52
style={styles.button52}
onPress={() => {
this.props.navigation.push("Timer");
}}
/>
</Center>
<View style={styles.rect2} />
</View>
</Center>
<Center>
<View style={styles.rect4}>
<View style={styles.rect5} />
<Button52
style={styles.button522}
onPress={() => {
this.props.navigation.push("Timer");
}}
/>
<View style={styles.rect6} />
</View>
</Center>
<Center horizontal>
<View style={styles.rect7}>
<View style={styles.rect8} />
<Button52
style={styles.button523}
onPress={() => {
this.props.navigation.push("Timer");
}}
/>
<View style={styles.rect9} />
</View>
</Center>
<Center horizontal>
<View style={styles.rect10}>
<View style={styles.rect11} />
<Button52
style={styles.button524}
onPress={() => {
this.props.navigation.push("Timer");
}}
/>
<View style={styles.rect12} />
</View>
</Center>
</View>
);
}
}
const styles = StyleSheet.create({
root: {
backgroundColor: "#f3f4f4",
flex: 1
},
statusBar: {},
button15: {
top: 56,
left: 338,
position: "absolute",
height: 36
},
scrollArea: {
height: 608.9,
width: 374,
top: 156,
left: 0,
position: "absolute",
backgroundColor: "rgba(244,244,245,1)",
opacity: 1
},
image: {
height: 73,
width: 301,
position: "absolute",
top: "6.83%"
},
rect3: {
height: 133,
width: 347,
top: 156,
position: "absolute"
},
rect: {
top: 0,
left: "0%",
width: 347,
height: 91,
position: "absolute",
backgroundColor: "rgba(255,255,255,1)",
opacity: 1
},
button52: {
top: 91,
height: 36,
position: "absolute"
},
rect2: {
top: "95.52%",
left: "0%",
width: 347,
height: 6,
position: "absolute",
backgroundColor: "rgba(255,255,255,1)",
opacity: 1
},
rect4: {
width: 347,
height: 132,
position: "absolute"
},
rect5: {
top: 0,
left: "0%",
width: 347,
height: 91,
position: "absolute",
backgroundColor: "rgba(255,255,255,1)",
opacity: 1
},
button522: {
top: 91,
left: "37.46%",
height: 35,
position: "absolute"
},
rect6: {
top: "95.52%",
left: "0%",
width: 347,
height: 6,
position: "absolute",
backgroundColor: "rgba(255,255,255,1)",
opacity: 1
},
rect7: {
top: "61.33%",
width: 347,
height: 133,
position: "absolute"
},
rect8: {
top: 0,
left: "0%",
width: 347,
height: 91,
position: "absolute",
backgroundColor: "rgba(255,255,255,1)",
opacity: 1
},
button523: {
top: 91,
left: "37.46%",
height: 35,
position: "absolute"
},
rect9: {
top: "95.52%",
left: "0%",
width: 347,
height: 6,
position: "absolute",
backgroundColor: "rgba(255,255,255,1)",
opacity: 1
},
rect10: {
top: "81.16%",
width: 347,
height: 133,
position: "absolute"
},
rect11: {
top: 0,
left: "0%",
width: 347,
height: 91,
position: "absolute",
backgroundColor: "rgba(255,255,255,1)",
opacity: 1
},
button524: {
top: 91,
left: "37.46%",
height: 35,
position: "absolute"
},
rect12: {
top: "95.52%",
left: "0%",
width: 347,
height: 6,
position: "absolute",
backgroundColor: "rgba(255,255,255,1)",
opacity: 1
}
});

In React Navigation you need to use the navigate method instead of push
this.props.navigation.navigate("Timer");
And to go back you use the goBack method instead of pop
this.props.navigation.goBack()
Read more about the navigation prop in the docs

Related

How to add text inside of the Camera View when using react-native-qrcode-scanner in react native

I am now using react-native-qrcode-scanner to read the QRcode but now have trouble when trying to add the text inside of the camera view. (Not top or bottom of the camera view but inside of it - more exactly under the marker position with align center)
The text is not displayed even though I add Text field with position: 'absolute'
import QRCodeScanner from 'react-native-qrcode-scanner';
return (
<QRCodeScanner
onRead={onSuccess}
reactivate={true}
showMarker
containerStyle={styles.cameraContainer}
cameraStyle={{
...styles.camera,
height: Dimensions.get('window').height - topOffset,
}}
topViewStyle={styles.topView}
markerStyle={styles.marker}
bottomViewStyle={styles.bottomView}
cameraProps={{
type: 'back',
}}
/>
);
const styles = StyleSheet.create({
cameraContainer: {
backgroundColor: theme.colors.background,
},
camera: {},
bottomView: {
height: 0,
flex: 0,
},
topView: {
height: 0,
flex: 0,
},
marker: {
borderWidth: 2,
borderRadius: 10,
borderColor: theme.colors.white,
}
});
You can use styling with position: absolute for the text element within a container.
Following sample works for me on iOS:
/* eslint-disable react-native/no-color-literals */
// #ts-nocheck
import React from "react"
// eslint-disable-next-line react-native/split-platform-components
import { View, StyleSheet, TouchableOpacity, Text, ToastAndroid } from "react-native"
import QRCodeScanner from "react-native-qrcode-scanner"
import { RNCamera } from "react-native-camera"
import Clipboard from "#react-native-community/clipboard"
const styles = StyleSheet.create({
cameraContainer: {
flex: 1,
},
container: {
backgroundColor: "#fff",
flex: 1,
height: "100%",
width: "100%",
},
flash: {
alignItems: "center",
backgroundColor: "#CCC",
borderRadius: 19,
height: 38,
justifyContent: "center",
position: "absolute",
right: 20,
top: 20,
width: 100,
zIndex: 1,
},
markerStyle: {
borderColor: "#ffffff",
top: -40,
},
})
export const BarcodeScannerScreen: React.FC = () => {
const [flashOn, setFlashOn] = React.useState(false)
const barcodeScanned = (barcode) => {
ToastAndroid.show("Code copied to clipboard", ToastAndroid.LONG)
Clipboard.setString(JSON.stringify(barcode.data))
console.log("Barcode: ", barcode.data)
}
const toggleFlash = () => {
setFlashOn(!flashOn)
}
const androidCameraPermissionOptions = {
title: "Camera permission required",
message: "To test QR-Code scan camera permission is required",
}
return (
<View style={styles.container}>
<TouchableOpacity style={styles.flash} onPress={toggleFlash}>
<Text>Flash on</Text>
</TouchableOpacity>
<QRCodeScanner
onRead={barcodeScanned}
cameraProps={{
androidCameraPermissionOptions: androidCameraPermissionOptions,
flashMode: flashOn
? RNCamera.Constants.FlashMode.torch
: RNCamera.Constants.FlashMode.off,
barCodeTypes: [RNCamera.Constants.BarCodeType.qr],
type: RNCamera.Constants.Type.back,
}}
showMarker={true}
reactivate={true}
reactivateTimeout={3000}
cameraStyle={styles.cameraContainer}
markerStyle={styles.markerStyle}
/>
<View
style={{
position: "absolute",
alignSelf: "center",
top: 300,
width: 50,
height: 50,
backgroundColor: "#ff00ff",
}}
>
<Text>Text</Text>
</View>
</View>
)
}
/* eslint-disable react-native/no-color-literals */
// #ts-nocheck
import React from "react"
// eslint-disable-next-line react-native/split-platform-components
import { View, StyleSheet, TouchableOpacity, Text, ToastAndroid } from "react-native"
import QRCodeScanner from "react-native-qrcode-scanner"
import { RNCamera } from "react-native-camera"
import Clipboard from "#react-native-community/clipboard"
const styles = StyleSheet.create({
cameraContainer: {
flex: 1,
},
container: {
backgroundColor: "#fff",
flex: 1,
height: "100%",
width: "100%",
},
flash: {
alignItems: "center",
backgroundColor: "#CCC",
borderRadius: 19,
height: 38,
justifyContent: "center",
position: "absolute",
right: 20,
top: 20,
width: 100,
zIndex: 1,
},
markerStyle: {
borderColor: "#ffffff",
top: -40,
},
})
export const BarcodeScannerScreen: React.FC = () => {
const [flashOn, setFlashOn] = React.useState(false)
const barcodeScanned = (barcode) => {
ToastAndroid.show("Code copied to clipboard", ToastAndroid.LONG)
Clipboard.setString(JSON.stringify(barcode.data))
console.log("Barcode: ", barcode.data)
}
const toggleFlash = () => {
setFlashOn(!flashOn)
}
const androidCameraPermissionOptions = {
title: "Camera permission required",
message: "To test QR-Code scan camera permission is required",
}
return (
<View style={styles.container}>
<TouchableOpacity style={styles.flash} onPress={toggleFlash}>
<Text>Flash on</Text>
</TouchableOpacity>
<QRCodeScanner
onRead={barcodeScanned}
cameraProps={{
androidCameraPermissionOptions: androidCameraPermissionOptions,
flashMode: flashOn
? RNCamera.Constants.FlashMode.torch
: RNCamera.Constants.FlashMode.off,
barCodeTypes: [RNCamera.Constants.BarCodeType.qr],
type: RNCamera.Constants.Type.back,
}}
showMarker={true}
reactivate={true}
reactivateTimeout={3000}
cameraStyle={styles.cameraContainer}
markerStyle={styles.markerStyle}
/>
<View
style={{
position: "absolute",
alignSelf: "center",
top: 300,
width: 50,
height: 50,
backgroundColor: "#ff00ff",
}}
>
<Text>Text</Text>
</View>
</View>
)
}

video keeps playing when I navigate to another screen

when I upload a video from my gallery and then try to navigate to the next screen,the video keeps playing in the background.
below is my code:
import React, {PureComponent} from 'react';
import {
StyleSheet,
Text,
TouchableOpacity,
View,
Animated,
ProgressBarAndroid,
} from 'react-native';
import {RNCamera} from 'react-native-camera';
import Icon from 'react-native-vector-icons/Entypo';
import ImagePicker from 'react-native-image-crop-picker';
import Video from 'react-native-video';
import { withNavigationFocus } from 'react-navigation';
class Shoot extends PureComponent {
constructor(props) {
super(props);
this.state = {
recording: false,
processing: true,
upload: false,
galleryVideo: '',
progress30: '',
progress60: '',
progress15: 0,
video: '',
progressStatus: 0,
progressStatus60: 0,
progressStatus15: 0,
videoPaused: false
};
}
render() {
return (
<View style={styles.container}>
{this.state.upload == true && (
<TouchableOpacity
style={{
backgroundColor: '#e75480',
position: 'absolute',
width: 80,
height: 30,
zIndex: 2,
padding: 5,
borderRadius: 5,
right: 0,
justifyContent: 'center',
alignContent: 'center',
}}
onPress={() => this.props.navigation.navigate('Post', {key: 1})}>
<Text style={{color: 'white', textAlign: 'center'}}>Next</Text>
</TouchableOpacity>
)}
{this.state.upload == false && (
<TouchableOpacity
style={{
position: 'absolute',
bottom: 0,
right: '15%',
justifyContent: 'center',
alignItems: 'center',
}}
onPress={this.video.bind(this)}>
<Icon name="image" size={30} color="white" />
<Text style={{color: 'white', fontWeight: 'bold'}}>Upload</Text>
</TouchableOpacity>
)}
<TouchableOpacity
onPress={this.take60sVideo.bind(this)}
style={{
width: 60,
height: 60,
justifyContent: 'center',
alignContent: 'center',
position: 'absolute',
bottom: 0,
left: '25%',
}}>
<Text style={{textAlign: 'center', color: 'red', fontSize: 15}}>
60s
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this.take15sVideo.bind(this)}
style={{
width: 60,
height: 60,
justifyContent: 'center',
alignContent: 'center',
position: 'absolute',
bottom: 0,
left: '5%',
}}>
<Text style={{textAlign: 'center', color: 'red', fontSize: 15}}>
15s
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this.take30sVideo.bind(this)}
style={styles.capture}></TouchableOpacity>
{this.state.progress30 === true && (
<View
style={{
width: '100%',
height: 15,
top: 0,
position: 'absolute',
bottom: 0,
zIndex: 2,
}}>
{/* <Animated.View
style={
([StyleSheet.absoluteFill],
{backgroundColor: '#8BED4F', width: '50%', height: 10})
}
/> */}
<ProgressBarAndroid
styleAttr="Horizontal"
progress={this.state.progressStatus}
indeterminate={false}
color="#e75480"
/>
</View>
)}
{this.state.progress60 === true && (
<View
style={{
width: '100%',
height: 15,
top: 0,
position: 'absolute',
bottom: 0,
zIndex: 2,
}}>
{/* <Animated.View
style={
([StyleSheet.absoluteFill],
{backgroundColor: '#8BED4F', width: '50%', height: 10})
}
/> */}
<ProgressBarAndroid
styleAttr="Horizontal"
progress={this.state.progressStatus60}
indeterminate={false}
color="#e75480"
/>
</View>
)}
{this.state.progress15 === true && (
<View
style={{
width: '100%',
height: 15,
top: 0,
position: 'absolute',
bottom: 0,
zIndex: 2,
}}>
{/* <Animated.View
style={
([StyleSheet.absoluteFill],
{backgroundColor: '#8BED4F', width: '50%', height: 10})
}
/> */}
<ProgressBarAndroid
styleAttr="Horizontal"
progress={this.state.progressStatus15}
indeterminate={false}
color="#e75480"
/>
</View>
)}
{this.state.video == '' ? (
<RNCamera
ref={(ref) => {
this.camera = ref;
}}
style={styles.preview}
type={RNCamera.Constants.Type.back}
flashMode={RNCamera.Constants.FlashMode.on}
androidCameraPermissionOptions={{
title: 'Permission to use camera',
message: 'We need your permission to use your camera',
buttonPositive: 'Ok',
buttonNegative: 'Cancel',
}}
androidRecordAudioPermissionOptions={{
title: 'Permission to use audio recording',
message: 'We need your permission to use your audio',
buttonPositive: 'Ok',
buttonNegative: 'Cancel',
}}
captureAudio={true}
/>
) : (
<Video
source={{uri: this.state.video}}
style={{
position: 'absolute',
top: 0,
left: 0,
alignItems: 'stretch',
bottom: 0,
right: 0,
height: '90%',
}}
resizeMode="cover"
repeat={true}
paused={this.state.videoPaused}
/>
)}
</View>
);
}
static getDerivedStateFromProps(nextProps, prevState) {
return {
...prevState,
videoPaused: !nextProps.navigation.isFocused()
}
}
video = () => {
ImagePicker.openPicker({
mediaType: 'video',
}).then((video) => {
this.setState({
galleryVideo: 1,
video: video.path,
upload: true,
});
});
};
take30sVideo = async () => {
if (this.camera) {
try {
const options = {
quality: 2,
videoBitrate: 8000000,
maxDuration: 30,
};
const promise = this.camera.recordAsync(options);
this.setState({progress30: true});
this.value = setInterval(() => {
if (this.state.progressStatus <= 1) {
this.setState({progressStatus: this.state.progressStatus + 0.01});
}
}, 100);
if (promise) {
this.setState({recording: true});
const data = await promise;
this.setState({recording: false, upload: true, progress30: false});
console.log(data);
console.log('upload', this.state.upload);
}
} catch (error) {
console.log(error);
}
}
};
take60sVideo = async () => {
if (this.camera) {
try {
const options = {
quality: 2,
videoBitrate: 8000000,
maxDuration: 60,
};
const promise = this.camera.recordAsync(options);
this.setState({progress60: true});
this.value = setInterval(() => {
if (this.state.progressStatus60 <= 1) {
this.setState({
progressStatus60: this.state.progressStatus60 + 0.01,
});
}
}, 100);
if (promise) {
this.setState({recording: true});
const data = await promise;
this.setState({recording: false, upload: true, progress60: false});
console.log(data);
console.log('upload', this.state.upload);
}
} catch (error) {
console.log(error);
}
}
};
take15sVideo = async () => {
if (this.camera) {
try {
const options = {
quality: 2,
videoBitrate: 8000000,
maxDuration: 15,
};
const promise = this.camera.recordAsync(options);
this.setState({progress15: true});
this.value = setInterval(() => {
if (this.state.progressStatus15 <= 1) {
this.setState({
progressStatus15: this.state.progressStatus15 + 0.01,
});
}
}, 100);
if (promise) {
this.setState({recording: true});
const data = await promise;
this.setState({recording: false, upload: true, progress15: false});
console.log(data);
console.log('upload', this.state.upload);
}
} catch (error) {
console.log(error);
}
}
};
}
export default withNavigationFocus(Shoot);
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: 'black',
},
preview: {
height: '90%',
justifyContent: 'flex-end',
alignItems: 'center',
},
capture: {
backgroundColor: '#e75480',
borderRadius: 40,
borderWidth: 3,
borderColor: 'red',
width: 60,
height: 60,
position: 'absolute',
bottom: 0,
justifyContent: 'center',
left: '45%',
alignContent: 'center',
},
});
I have already tried withNavigationFocus but it is not working,let me know if any other way is there,also let me know if anything else is required for clarification.
Any suggestion would be great.
I have finally resolved this issue by creating a function for next button and setting the state of paused to true whenever the screen navigates to the other screen.
Hope,that helps.
Setting the video screen as "fullScreenModal" worked for me:
("react-native": "0.71.2", "#react-navigation/native": "^6.1.3", "react-native-video": "^5.2.1")
react navigation stack definition:
function Stack() {
return (
<Stack.Navigator>
<Stack.Screen name="SomeScreen" component={SomeScreen} />
<Stack.Screen
name="FullScreenVideo"
component={FullScreenVideo}
options={{ headerShown: false, presentation: "fullScreenModal" }}
/>
</Stack.Navigator>;
)
}
FullScreenVideo.jsx
import React from "react";
import Video from "react-native-video";
import { StyleSheet } from "react-native";
export default function FullScreenVideo({ navigation, route }) {
const videoUri = route.params.uri;
return (
<Video
source={{ uri: videoUri }}
controls
onEnd={() => navigation.pop()}
style={styles.backgroundVideo}
/>
);
}
var styles = StyleSheet.create({
backgroundVideo: {
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0,
},
});
I think you also could killed or paused the video when the component will be unmounted:
// Class component
componentWillUnmount() {
videoRef.seek(0)
this.setState({isPaused: true})
}
OR
// functional component
useEffect(() => {
return () => {
videoRef.current.seek(0)
setIsPaused(true)
}
}, [])
You also can use methods from react native navigation:
Call a function when focused screen changes
I hope it’ll help someone

Why won't my top level react-native component expand to the full dimensions?

I'm using next.js if that matters and my pages/_app.tsx has:
function MyApp({ Component, pageProps }: AppProps) {
return (
<PaperProvider theme={customTheme}>
<View style={{ flex: 1, top: 0, left: 0, height: '100%', width: '100%', zIndex: 10, position: 'absolute', backgroundColor: 'red' }}>
<Text> Here</Text>
</View>
</PaperProvider>
)
}
export default MyApp
and customTheme is:
import { DefaultTheme } from 'react-native-paper';
export const customTheme = {
...DefaultTheme,
dark: false,
colors: {
...DefaultTheme.colors,
primary: '#247BA0',
accent: '#70C1B3',
error: '#FF1654',
disabled: '#F3FFBD',
placeholder: '#D3EDBE',
}
}
I see Text, but no red background. What am I missing?
Ok the problem here is the use of position: 'absolute' with height: '100%', delete one of these properties in your style object and it should work.
If you want the full screen to have background color change height: '100%' to height: Dimensions.get("window").height

Show a custom pop-up alert overlay on-top of header - React Navigation

I'm trying to show this custom modal pop-up over the top of the Header component in React Navigation. See the pic below:
I've tried setting zIndexes on the overlay and parent view containers, but the header is seperate in the component stack. Anyone know how to solve this? I've tried putting a BlurView over the header component.
import React, { Component } from "react";
import PropTypes from "prop-types";
import { StyleSheet, View, Animated, Text, TextInput } from "react-native";
import BlockButton from "../common/BlockButton";
import { BlurView } from "react-native-blur";
export default class BlurAlert extends Component {
static navigationOptions = ({ navigation }) => {
return {
headerStyle: {}
};
};
constructor(props) {
super(props);
this.state = {
visible: this.props.visible,
title: null,
body: null
};
}
render() {
if (this.props.visible) {
return (
<View style={styles.wrapper}>
<BlurView style={styles.blurView} blurType="dark" blurAmount={5} />
<View style={styles.box}>
<Text style={styles.titleText}>{this.props.title}</Text>
<Text style={styles.bodyText}>{this.props.body}</Text>
{this.props.children}
<BlockButton
backgroundColor={"#F0AC8F"}
borderColor={"#F0AC8F"}
fontColor={"white"}
title={this.props.buttonText}
padding={23}
marginTop={25}
disabled={false}
onPress={this.props.onClosed}
/>
</View>
</View>
);
} else {
return <View />;
}
}
}
BlurAlert.propTypes = {
title: String,
body: String,
buttonText: String,
visible: Boolean
};
BlurAlert.defaultProps = {
visible: false,
buttonText: "OK"
};
const styles = StyleSheet.create({
wrapper: {
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0,
height: "100%",
width: "100%",
zIndex: 9999
},
blurView: {
flex: 1,
zIndex: 99999
},
container: {
margin: 25,
zIndex: 99999,
position: "relative",
top: 0,
left: 0,
bottom: 0,
right: 0
},
box: {
backgroundColor: "white",
padding: 20,
position: "absolute",
top: "15%",
borderColor: "black",
borderWidth: StyleSheet.hairlineWidth,
margin: 25,
alignItems: "center",
shadowColor: "#000",
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 3,
zIndex: 99999,
width: "85%"
},
titleText: {
fontFamily: "Lora",
fontSize: 20
},
bodyText: {
marginTop: 15,
textAlign: "center",
fontFamily: "Lora",
fontSize: 16,
lineHeight: 20
}
});
You can try using "Modal":
import React, { Component } from "react";
import PropTypes from "prop-types";
import { StyleSheet, View, Animated, Text, TextInput, Modal } from "react-native";
import BlockButton from "../common/BlockButton";
import { BlurView } from "react-native-blur";
export default class BlurAlert extends Component {
static navigationOptions = ({ navigation }) => {
return {
headerStyle: {}
};
};
constructor(props) {
super(props);
this.state = {
visible: this.props.visible,
title: null,
body: null
};
}
render() {
if (this.props.visible) {
return (
<Modal
transparent
animationType="fade"
visible={this.state.visible}
onRequestClose={() => {
console.log('Modal has been closed.');
}}>
>
<View style={styles.wrapper}>
<BlurView style={styles.blurView} blurType="dark" blurAmount={5} />
<View style={styles.box}>
<Text style={styles.titleText}>{this.props.title}</Text>
<Text style={styles.bodyText}>{this.props.body}</Text>
{this.props.children}
<BlockButton
backgroundColor={"#F0AC8F"}
borderColor={"#F0AC8F"}
fontColor={"white"}
title={this.props.buttonText}
padding={23}
marginTop={25}
disabled={false}
onPress={this.props.onClosed}
/>
</View>
</View>
</Modal>
);
} else {
return <View />;
}
}
}
BlurAlert.propTypes = {
title: String,
body: String,
buttonText: String,
visible: Boolean
};
BlurAlert.defaultProps = {
visible: false,
buttonText: "OK"
};
const styles = StyleSheet.create({
wrapper: {
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0,
height: "100%",
width: "100%",
zIndex: 9999
},
blurView: {
flex: 1,
zIndex: 99999
},
container: {
margin: 25,
zIndex: 99999,
position: "relative",
top: 0,
left: 0,
bottom: 0,
right: 0
},
box: {
backgroundColor: "white",
padding: 20,
position: "absolute",
top: "15%",
borderColor: "black",
borderWidth: StyleSheet.hairlineWidth,
margin: 25,
alignItems: "center",
shadowColor: "#000",
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 3,
zIndex: 99999,
width: "85%"
},
titleText: {
fontFamily: "Lora",
fontSize: 20
},
bodyText: {
marginTop: 15,
textAlign: "center",
fontFamily: "Lora",
fontSize: 16,
lineHeight: 20
}
});

How to apply absolute position to custom Component in React Native?

this something stange but as you can see here: https://snack.expo.io/B1_5TLFvW the custom component "Cualquiera" is not positioning with absolute position, it's showing in stack, just like a list, and View components are good, if I change "class Cualquiera extends to Component" to "class Cualquiera extends View" it then it takes the position correctly, I have a custom component in my code that is not taking the absolute positions even if I set it to extend View, it shows the components as list too. How can I make it work with absolute positions extending Component?
thank you!!
here the code
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class Position extends Component {
render() {
return (
<View style={styles.container}>
<Cualquiera numero={1} style={styles.box1} />
<Cualquiera numero={4} style={styles.box4} />
<View numero={2} style={styles.box2}><Text style={styles.text}>2</Text></View>
<View numero={3} style={styles.box3}><Text style={styles.text}>3</Text></View>
</View>
);
}
}
class Cualquiera extends Component {
render() {
return (
<View
style={{
backgroundColor: '#49f',
borderWidth: 0.5,
borderColor: '#f05',
padding: 20,
}}>
<Text style={styles.text}>{this.props.numero}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
// flex: 1
},
box1: {
position: 'absolute',
top: 40,
left: 40,
width: 100,
height: 100,
backgroundColor: 'red',
},
box2: {
position: 'absolute',
top: 80,
left: 80,
width: 100,
height: 100,
backgroundColor: 'blue',
},
box3: {
position: 'absolute',
top: 120,
left: 120,
width: 100,
height: 100,
backgroundColor: 'green',
},
box4: {
position: 'absolute',
top: 160,
left: 160,
width: 100,
height: 100,
backgroundColor: 'yellow',
},
text: {
color: '#ffffff',
fontSize: 40,
},
});
The Cualquiera component is a custom component. The styles prop you pass into it isn't used for styling. If you want to pass in styles, pass in the style prop into view style prop like this:
class Cualquiera extends Component {
render() {
return (
<View
style={[
{ backgroundColor: 'blue'}, // pass in your main styles here
this.props.style // styles passed by props will be used
]}
/>
)
}