How do i set a background image to custom DrawerNavigator in react-navigation - react-native

My issue is, that i want the image is overflowing the Drawer
and does not fit the view width
I use contentComponent to have a custom Drawer.
the answer in the link below shows kinda what i want to achieve.
The issue though is, that width and heigth are given in absolute
values. This won't be working for tablet, iphones and android phones.
Any ideas?
export default StyleSheet.create({
...ApplicationStyles.screen,
container: {
//marginTop: Metrics.navBarHeight,
flex: 1,
flexDirection: 'column',
alignItems: 'stretch',
},
contentContainer: {
backgroundColor: 'transparent'
},
drawerImage: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
opacity: 0.05,
backgroundColor: 'green'
// resizeMode: "stretch"
},
render () {
const { navigation } = this.props
return (
<View style={styles.container}>
<Image source={Images.drawerBackground} style={styles.drawerImage}/>
<ScrollView style={styles.contentContainer}>
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerButton
iconName='ios-map'
text='Map'
onPress={() => navigation.navigate('MapView')}
/>
<DrawerButton
iconName='md-trending-up'
text='Elevation'
onPress={() => navigation.navigate('Elevation')}
/>
<DrawerButton
iconName='md-people'
text='Friends'
onPress={() => navigation.navigate('Friends')}
/>
<DrawerButton
iconName='md-person'
text='Profile'
onPress={() => navigation.navigate('Profile')}
/>
<DrawerButton
iconName='md-settings'
text='Settings'
onPress={() => navigation.navigate('Settings')}
/>
<View style={styles.checkinBtn}>
<CheckinButton
iconName='md-pin'
text='Checkin Location'
onPress={() => navigation.navigate('Settings')}
/>
</View>
</SafeAreaView>
</ScrollView>
<View style={styles.footer}>
<Text style={styles.text}>
........
</Text>
</View>
</View>
)
}
}
How to set a background Image of Navigator in React-Native

try using ImageBackground instead of Image and wrap all your elements into it
Refer the official docs here

import { ImageBackground } from "react-native";
<ImageBackground source={require('../../assets/images/AImg.png')} style={{ width: 100, height: 100}}>
//ur view/text flows here.....
</ImageBackground>
import and add ImageBackground
https://facebook.github.io/react-native/docs/images.html#background-image-via-nesting

Related

KeyboardAvoidingView doesn't work properly on my app

I searched a lot about this issue and I don't know what to do now so I decided to ask here and any help would be appreciated. in my register screen I have some input that user must fill and for the last one I need to avoid keyboard overlay. so I used KeyboardAvoidingView component to solve this but as you can see in the screenshot the device keyboard still overlay my input (birth date).
here is my code for this screen :
import React, { useState } from 'react';
import { View, Text, KeyboardAvoidingView, Image, Dimensions, PixelRatio, StyleSheet } from 'react-native';
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';
import { COLORS } from '../Constants/COLORS';
import PrimaryButton from '../Components/PrimaryButton';
import PrimaryInput from '../Components/PrimaryInput';
import CheckBox from '../Components/CheckBox';
const Register = (props) => {
const [lisenceTerm, setLisenceTerm] = useState(true);
const [privacyPolicy, setPrivacyPolicy] = useState(true);
return (
<View style={styles.screen}>
<View style={styles.imageContainer}>
<Image style={styles.image} source={require('../assets/Img/office_5.jpg')} />
</View>
<View style={styles.loginContainer}>
<View style={styles.headerContainer}>
<Text style={styles.headerText}>Join us</Text>
</View>
<KeyboardAvoidingView style={styles.inputContainer}>
<PrimaryInput placeholder='Name Surname' />
<PrimaryInput placeholder='Your Email' />
<PrimaryInput placeholder='Phone Number (05***)' />
<PrimaryInput placeholder='Birth Date' />
</KeyboardAvoidingView>
<View style={styles.checkBoxContainer}>
<CheckBox text='Kvkk sözleşmesini okudum, kabul ediyorum' active={lisenceTerm} onPress={() => setLisenceTerm(!lisenceTerm)} />
<CheckBox text='Kullanıcı sözleşmesini okudum, kabul ediyorum' active={privacyPolicy} onPress={() => setPrivacyPolicy(!privacyPolicy)} />
</View>
<View style={styles.buttonsContainer}>
<PrimaryButton
buttonStyle={styles.button}
textStyle={styles.buttonText}
title='Register' />
</View>
</View>
</View>
)
}
const styles = StyleSheet.create({
screen: {
flex: 1,
},
imageContainer: {
width: '100%',
height: '34%'
},
image: {
width: '100%',
height: '100%'
},
loginContainer: {
backgroundColor: 'white',
width: '100%',
height: '71%',
position: 'absolute',
zIndex: 1,
bottom: 0,
borderTopLeftRadius: 40,
borderTopRightRadius: 40,
alignItems: 'center'
},
buttonsContainer: {
width: '100%',
justifyContent: 'center',
alignItems: 'center'
},
button: {
justifyContent: 'center',
alignItems: 'center',
width: '75%',
paddingVertical: '3%',
marginTop: hp(1.2),
borderRadius: hp(3.5),
backgroundColor: COLORS.royalBlue
},
buttonText: {
fontSize: hp(3.2),
fontFamily: 'BalooPaaji2ExtraBold',
color: 'white'
},
arrow: {
right: 20
},
inputContainer: {
width: '100%',
justifyContent: 'center',
alignItems: 'center',
marginBottom: hp(1),
},
headerContainer: {
marginTop: hp(3),
marginBottom: hp(2),
width: '75%',
},
headerText: {
fontSize: hp(3.5),
fontFamily: 'BalooPaaji2Bold',
color: COLORS.royalBlue
},
checkBoxContainer: {
width: '70%',
justifyContent: 'flex-start',
marginBottom: hp(1)
}
})
export default Register;
and here below is the result. btw I used behavior and keyboardVerticalOffset props to control the way this component behave but still same problem.
Your KeyboardAvoidingView component must be on top of render tree
In order to scroll onto your Join us view, you must set a ScrollView in your KeyboardAvoidingView and those component must be on top of renderer.
Try this (based on my iOS / android setup) :
import { KeyboardAvoidingView, ScrollView } from 'react-native';
const Register = (props) => {
const [lisenceTerm, setLisenceTerm] = useState(true);
const [privacyPolicy, setPrivacyPolicy] = useState(true);
return (
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={(Platform.OS === 'ios') ? 'padding' : null}
enabled
keyboardVerticalOffset={Platform.select({ ios: 80, android: 500 })}>
<ScrollView>
<View style={styles.screen}>
<View style={styles.imageContainer}>
<Image style={styles.image} source={require('../assets/Img/office_5.jpg')} />
</View>
<View style={styles.loginContainer}>
<View style={styles.headerContainer}>
<Text style={styles.headerText}>Join us</Text>
</View>
<View style={styles.inputContainer}>
<PrimaryInput placeholder='Name Surname' />
<PrimaryInput placeholder='Your Email' />
<PrimaryInput placeholder='Phone Number (05***)' />
<PrimaryInput placeholder='Birth Date' />
</View>
<View style={styles.checkBoxContainer}>
<CheckBox text='Kvkk sözleşmesini okudum, kabul ediyorum' active={lisenceTerm} onPress={() => setLisenceTerm(!lisenceTerm)} />
<CheckBox text='Kullanıcı sözleşmesini okudum, kabul ediyorum' active={privacyPolicy} onPress={() => setPrivacyPolicy(!privacyPolicy)} />
</View>
<View style={styles.buttonsContainer}>
<PrimaryButton
buttonStyle={styles.button}
textStyle={styles.buttonText}
title='Register' />
</View>
</View>
</View>
</ScrollView>
</KeyboardAvoidingView>
)
}
you need to install react-native-keyboard-aware-scroll-view by
yarn add react-native-keyboard-aware-scroll-view
and you need to wrap KeyboardAwareScrollView instead of KeyboardAvoidingView
like
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
<KeyboardAwareScrollView>
<View>
...
</View
</KeyboardAwareScrollView>
import { useHeaderHeight } from "#react-navigation/elements"
import {
Keyboard,
Platform,
TouchableWithoutFeedback,
View,
KeyboardAvoidingView
} from "react-native"
const Chat = () => {
// This is the crucial variable we will place it in
// KeyboardAvoidingView -> keyboardVerticalOffset
const headerHeight = useHeaderHeight()
return (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<KeyboardAvoidingView
style={{ position: "absolute", bottom: 0, left: 0, right: 0 }}
behavior={Platform.OS === "ios" ? "padding" : "height"}
// If you want the input not to stick exactly to the keyboard
// add a const here for example headerHeight + 20
keyboardVerticalOffset={headerHeight}
>
<View style={{ flex: 1, justifyContent: "flex-end" }}>
<InputWrapper>
<RawInput />
</InputWrapper>
</View>
</KeyboardAvoidingView>
</TouchableWithoutFeedback>
)
}
Also take a look at this article it might be helpful: https://medium.com/#nickyang0501/keyboardavoidingview-not-working-properly-c413c0a200d4

React Native - Image bigger than parent

Like in tinder, i have a screen with 3 Image Pickers. When I pick an image from the gallery, I want it to persist inside the TouchableOpacity container. However, the image overlaps the container.
I have been been trying various things mentioned here but the image still overlaps like in the image below:
What is the problem?
/* eslint-disable react-native/no-inline-styles */
import React, { useState } from 'react'
import {
Text,
View,
Image,
Button,
TouchableOpacity,
StyleSheet,
Dimensions,
} from 'react-native'
import ImagePicker from 'react-native-image-crop-picker'
import { FontAwesomeIcon } from '#fortawesome/react-native-fontawesome'
import { faPlusCircle } from '#fortawesome/free-solid-svg-icons'
import Colors from '../../../constants/Colors'
const { width: WIDTH } = Dimensions.get('window')
const ProfileEdit = () => {
const [photo, setPhoto] = useState(null)
const handleChoosePhoto = () => {
ImagePicker.openPicker({
width: 300,
height: 400,
cropping: true,
}).then((image) => {
setPhoto({
uri: image.path,
width: image.width,
height: image.height,
mime: image.mime,
})
console.log(image)
})
}
return (
<View style={styles.main}>
<View style={styles.button_row}>
<View style={styles.buttonWrapper}>
<TouchableOpacity
onPress={() => handleChoosePhoto()}
style={styles.button}>
{photo ? (
<Image source={photo} style={styles.photo} />
) : (
<FontAwesomeIcon
icon={faPlusCircle}
color={Colors.defaultColor}
size={22}
style={styles.icon}
/>
)}
</TouchableOpacity>
</View>
<View style={styles.buttonWrapper}>
<TouchableOpacity
onPress={() => handleChoosePhoto()}
style={styles.button}>
<FontAwesomeIcon
icon={faPlusCircle}
color={Colors.defaultColor}
size={22}
style={styles.icon}
/>
</TouchableOpacity>
</View>
<View style={styles.buttonWrapper}>
<TouchableOpacity
onPress={() => handleChoosePhoto()}
style={styles.button}>
<FontAwesomeIcon
icon={faPlusCircle}
color={Colors.defaultColor}
size={22}
style={styles.icon}
/>
</TouchableOpacity>
</View>
</View>
</View>
)
}
const styles = StyleSheet.create({
main: {
flex: 1,
},
icon: {},
button: {
height: `${100}%`,
backgroundColor: Colors.defaultWhite,
padding: 2,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 3,
},
buttonWrapper: {
width: WIDTH / 3,
padding: 10,
},
button_row: {
flex: 0.3,
flexWrap: 'wrap',
flexDirection: 'row',
},
photo: {
width: WIDTH / 2,
height: WIDTH / 2,
// borderRadius: 3,
resizeMode: 'contain',
},
})
export default ProfileEdit
correct answer as described here
"However because images will try to set the width and height based on the actual size of the image, you need to override these style properties"
<Image
style={{
flex: 1,
alignSelf: 'stretch',
width: undefined,
height: undefined
}}
source={require('../../assets/images/onboarding-how-it-works.png')}
/>
Instead of calculating image width try this:
<TouchableOpacity
onPress={() => handleChoosePhoto()}
style={styles.button}>
{photo ? (
<View style={styles.photoContainer}>
<Image source={photo} style={styles.photo} />
</View>
) : (
<FontAwesomeIcon
icon={faPlusCircle}
color={Colors.defaultColor}
size={22}
style={styles.icon}
/>
)}
</TouchableOpacity>
const styles = StyleSheet.create({
photoContainer: {
// flex: 1
},
photo: {
height: WIDTH / 2,
width: '100%',
resizeMode: 'contain'
}
});
I prefer ImageBackground instead. Below is the code to achieve you the desired View:
<ImageBackground
imageStyle={styles.image}
style={styles.imageContainer}
source={{uri: this.state.imageUri}}>
<TouchableOpacity onPress={this._pickImage} style={{
height: WIDTH/2,
width: WIDTH/2,
justifyContent: "center",
alignItems: "center"}}>
<Entypo name="camera" color={Colors.GREY} size={35}/>
</TouchableOpacity>
</ImageBackground>

onPress event not working inside the Animated View when it's position is absolute

I'm building a custom header. onPress event of the touchable opacity component is not working when I give components style prop - 'position:"absolute"' . But it works perfectly when I comment on the style property - position.
I couldn't find a solution for this elsewhere. Please help.
<Animated.View
style={{
elevation:
params !== undefined && params.elevation !== undefined
? params.elevation
: null,
position: "absolute",
top: 0,
left: 0,
backgroundColor:
params !== undefined && params.headerBgColor !== undefined
? params.headerBgColor
: "red",
width: "100%",
height:
params !== undefined && params.changingHeight !== undefined
? params.changingHeight
: 50,
justifyContent: "space-between",
alignItems: "center",
flexDirection: "row",
paddingHorizontal: 20
}}
>
<TouchableOpacity style={{}} onPress={() => console.log("hello")}>
<View style={{}}>
<Image
style={styles.menuIcon}
source={require("../../assets/images/Menu-512.png")}
/>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => console.log("image")}>
<View style={{}}>
<Image
style={styles.profImage}
source={require("../../assets/images/user.png")}
/>
</View>
</TouchableOpacity>
</Animated.View>;
You should put your absolutely positioned Animated.View as the last child in the screen component. Otherwise, the view that occupies the rest of the screen will become the responder to touches.
const Screen = () => {
return <View style={{ flex: 1}}>
<View style={{flex: 1}}>
//actual screen content
</View>
<Animated.View // header
...props
></Animated.View>
</View>
In the DOM, the component that comes after another component is put "above" it. So, if you do this, your header will be above the actual screen content view and, therefore, become the responder when pressed.
its working on my case checkout below code:
or checkout my snack example : https://snack.expo.io/#immynk/header_demo
either you missing some params which are providing or getting null on condition check kindly confirm it hope this answer will help you
import * as React from 'react';
import {
Text,
View,
StyleSheet,
Animated,
TouchableOpacity,
Image,
} from 'react-native';
import Constants from 'expo-constants';
export default class App extends React.Component {
render() {
return (
<View>
<Text>Hello this is demo of flexdirection of box color</Text>
<Animated.View
style={{
position: 'absolute',
top: 0,
left: 0,
backgroundColor: 'red',
width: '100%',
height: 50,
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row',
paddingHorizontal: 20,
}}>
<TouchableOpacity style={{}} onPress={() => alert("hello","hello")}>
<View style={{}}>
<Image
source={{ uri: 'https://reactjs.org/logo-og.png' }}
style={{ width: 50, height: 65 }}
/>
</View>
</TouchableOpacity>
<TouchableOpacity style={{}} onPress={() => alert("hello","hello")}>
<View style={{}}>
<Image
source={{ uri: 'https://reactjs.org/logo-og.png' }}
style={{ width: 50, height: 65 }}
/>
</View>
</TouchableOpacity>
</Animated.View>
</View>
);
}
}

React Native Components disappear on re-render

My app has a homescreen built out of hexagons. Since flex doesn't handle diagonal alignment well I used the transform prop to move the hexagons manually into alignment. However, when the app is re-rendered, the hexagons seem to disappear and reappear at random. It usually takes ~8 renders and then the hexagons will all magically reappear.
EDIT: The invisible hexagons can still be pressed, and when the user navigates back to the homescreen, all the hexagons are visible.
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, Dimensions, TouchableOpacity } from 'react-native';
class Home extends Component {
constructor(props){
super(props);
}
render() {
return (
<View style={style.columnHexView}>
<View>
<TouchableOpacity
activeOpacity = {.5}
style={style.HexOpacity}
>
<Image style={style.Hex}source={require('./images/logo.png')} />
</TouchableOpacity>
</View>
<View>
<TouchableOpacity
activeOpacity = {.5}
style={style.HexOpacity}
>
<Image style={style.Hex}source={require('./images/emptyhex.png')}/>
</TouchableOpacity>
</View>
<View style={{transform:([
{translateY:(Dimensions.get('window').height/10)*-2.5},
{translateX:(Dimensions.get('window').height/10)*-.84}
])}}>
<TouchableOpacity
activeOpacity = {.5}
style={style.HexOpacity}
onPress={() => this.props.navigation.navigate("documentList")}
>
<Image style={style.Hex}source={require('./images/documenthex.png')} />
</TouchableOpacity>
</View>
<View style={{transform:([
{translateY:(Dimensions.get('window').height/10)*-3.5},
{translateX:(Dimensions.get('window').height/10)*.84}
])}}>
<TouchableOpacity
activeOpacity = {.5}
style={style.HexOpacity}
onPress={() => this.props.navigation.navigate("Settings")}
>
<Image style={style.Hex}source={require('./images/cog.png')} />
</TouchableOpacity>
</View>
<View style={{transform:([
{translateY:(Dimensions.get('window').height/10)*-5}
])}}>
<TouchableOpacity
activeOpacity = {.5}
style={style.HexOpacity}
onPress={() => this.props.navigation.navigate("ToDo")}
>
<Image style={style.Hex}source={require('./images/todohex.png')}/>
</TouchableOpacity>
</View>
<View style={{transform:([
{translateY:(Dimensions.get('window').height/10)*-4.5},
{translateX:(Dimensions.get('window').height/10)*.84}
])}}>
<TouchableOpacity
activeOpacity = {.5}
style={style.HexOpacity}
>
<Image style={style.Hex}source={require('./images/emptyhex.png')}/>
</TouchableOpacity>
</View>
<View style={{transform:([
{translateY:(Dimensions.get('window').height/10)*-5.5},
{translateX:(Dimensions.get('window').height/10)*-.84}
])}}>
<TouchableOpacity
activeOpacity = {.5}
style={style.HexOpacity}
>
<Image style={style.Hex}source={require('./images/emptyhex.png')}/>
</TouchableOpacity>
</View>
</View>
);
}
}
const style = StyleSheet.create({
columnHolder: {
flex: 0,
height: Dimensions.get('screen').height,
width: Dimensions.get('screen').width,
backgroundColor: '#424242',
flexDirection: 'row',
},
columnHexView: {
backgroundColor:'#424242',
alignItems: "center",
justifyContent: 'center',
flex: 1,
},
Hex: {
aspectRatio: 100/85,
maxHeight: Dimensions.get('window').height/10,
resizeMode: 'contain',
flexDirection: 'column',
flex: 0,
flexWrap: 'wrap'
},
hexHold:{
},
HexOpacity: {
justifyContent: 'center',
resizeMode: 'stretch',
display: 'flex',
maxHeight: Dimensions.get('window').height/5
}
}
)
export default Home
In case anyone sees this, the solution was to use cover resize mode instead of contain. I suspect that it was only rendering some hexagons due to slight overlap in between the hexagons.

React-Native: how to fill fullsize screen without explicit Width and Height?

I want to create a fullsize-screen with the child-view (a video player) that is rendered over the full size of the screen. I only get it work when i pass explicitly width and height to the component.
But i know that there is a property called "flex". In many tutorials they do something like "flex: 1", but for me it nowhere does what it is supposed to.
(For the sake of completeness, the video-player is not part of the question. I can also replace the <video> tag with <Image> or each other kind of view and get the same results)
render() {
const uri = this.props.uri
return (
<KeyboardAwareScrollView keyboardShouldPersistTaps="always" >
<TouchableWithoutFeedback onPress={RouterActions.pop}>
<Video source={{uri: uri}}
ref={(ref) => {
this.player = ref
}}
style={s.fullsize}
/>
</TouchableWithoutFeedback>
<TouchableOpacity onPress={RouterActions.pop} style={s.closeBtn}>
<Icon name="times-circle-o" size={20} color="white" />
</TouchableOpacity>
</KeyboardAwareScrollView>
)
}
My styles:
This is only working when i pass the width and height:
const s = StyleSheet.create({
fullsize: {
backgroundColor: 'black',
//flex: 1,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
closeBtn: {
position: 'absolute',
left: 20,
top: 25,
},
});
I only tried out this one, but then the screen will be empty because of the -Component has a width and height of 0 each.
const s = StyleSheet.create({
fullsize: {
backgroundColor: 'black',
flex: 1, // this is not working
left: 0,
right: 0,
top: 0,
bottom: 0
},
});
I believe doing flex: 1 will make it take up all the space provided by it's parent element. In your case, none of your parent elements have any styling so try this out:
render() {
const uri = this.props.uri
return (
<View style={{ flex: 1 }}>
<TouchableWithoutFeedback style={{ flex: 1 }} onPress={RouterActions.pop}>
<Video source={{uri: uri}}
ref={(ref) => {
this.player = ref
}}
style={{ flex: 1 }}
/>
</TouchableWithoutFeedback>
<TouchableOpacity onPress={RouterActions.pop} style={s.closeBtn}>
<Icon name="times-circle-o" size={20} color="white" />
</TouchableOpacity>
</View>
)
}