React Native Components disappear on re-render - react-native

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.

Related

text above row of buttons in React Native

This should be relatively easy for a React Native expert. I simply wish to display some text, and then under the text should be a row of buttons. Beginning with the row of buttons, this seems to work fine:
constructor(props) {
super(props);
this.state = {
titleText: "Bird's Nest",
bodyText: "This is not really a bird nest."
};
}
render() {
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button title="Camera"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Start"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Website"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Stop"/>
</View>
</View>
); //return
} //render
const styles = StyleSheet.create({
page:{
flex:1,
backgroundColor: "#000",
paddingTop:50,
color: 'white'
},
container: {
flex: 1,
backgroundColor: "#000",
flexDirection: 'row',
alignItems: 'center',
justifyContent: "center"
},
buttonContainer: {
flex: 1,
},
container1: {
backgroundColor: 'powderblue',
height : 100
},
container2: {
backgroundColor: 'grey',
height : 100
},
baseText: {
fontFamily: "Cochin"
},
titleText: {
fontSize: 20,
fontWeight: "bold",
color: 'white'
}
});
When I attempt to add the text...it is functional however the text is positioned before the row of buttons instead of placement over/above the row of buttons. Here is the same code inclusive of the text:
...
render() {
return (
<View style={styles.container}>
<Text style={styles.baseText}>
<Text style={styles.titleText} onPress={this.onPressTitle}>
{this.state.titleText}
{"\n"}
{"\n"}
</Text>
<Text numberOfLines={5}>{this.state.bodyText}</Text>
</Text>
<View style={styles.buttonContainer}>
<Button title="Camera"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Start"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Website"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Stop"/>
</View>
</View>
); //return
} //render
...
So basically the 'text' is rendered and then the 4 buttons are rendered with everything all 'crushed' together...all within the same row. There probably needs to be some sort of 'column' for the text however I have no idea how to combine 'column' and 'row' (necessary for the buttons) in React Native (within the same page 'container'). Or perhaps there is some other way to do it?
In addition, it would be nice if the row of buttons appeared along the bottom of the device screen instead of centered. I had changed the 'alignItems' in the 'styles.container' to 'baseline' (before I added any text) however that did not accomplish the desired result. I thank you in advance for any advice.
UPDATE:
At this point I have modified my code above and what I have now is something more along the lines of what I am seeking...although not perfect. There is probably a better way however here is what my code looks like now:
import BoxContainer from './BoxContainer';
render() {
return (
<View style={styles.page}>
<BoxContainer style={styles.container1}>
<Text>Bunch of text here.</Text>
</BoxContainer>
<BoxContainer style={styles.container2}>
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button title="Camera"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Start"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Website"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Stop"/>
</View>
</View>
</BoxContainer>
</View>
); //return
} //render
The code for 'BoxContainer' is here, a resource I found on the Internet somewhere:
import React from 'react';
import { StyleSheet, View} from 'react-native';
const BoxContainer = props => {
return (
<View style={{...styles.boxContainer, ...props.style}}>
{props.children}
</View>
);
};
const styles = StyleSheet.create({
boxContainer:{
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,
shadowRadius: 2,
height:200,
margin: 20,
alignItems: 'center',
justifyContent: 'center'
}
});
export default BoxContainer;
As mentioned, this is close to what I am seeking however I wish I could find a way to do it without the structured box containers...or perhaps that is necessary in React Native...?

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

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>
);
}
}

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

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

Two buttons with equal width horizontally fill the screen in React Native

I need to create two or more buttons which will be of equal width and horizontally aligned, based on screen width button width may vary.
You can wrap you Buttons into flexed Views :
import React, { Component } from 'react';
import { Button, View, StyleSheet } from 'react-native';
export default const FlexedButtons () => (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button title="Button 1"/>
</View>
<View style={styles.buttonContainer}>
<Button title="Button 2"/>
</View>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
buttonContainer: {
flex: 1,
}
});
Here is a working example on Sketch:
https://snack.expo.io/SyMpPSise
import React, { Component } from 'react';
import { Button, StyleSheet, View } from 'react-native';
export default class ButtonExample extends Component {
_onPressButton() {
alert('You tapped the button!')
}
render() {
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button
onPress={this._onPressButton}
title="Press Me"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={this._onPressButton}
title="Press Me"
color="#841584"
/>
</View>
<View style={styles.alternativeLayoutButtonContainer}>
<Button
onPress={this._onPressButton}
title="This looks great!"
/>
<Button
onPress={this._onPressButton}
title="OK!"
color="#841584"
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
buttonContainer: {
margin: 20
},
alternativeLayoutButtonContainer: {
margin: 20,
flexDirection: 'row',
justifyContent: 'space-between'
}
});
<View style={styles.menuContainer}>
<TouchableOpacity onPress={() => this.pressLink('Home')}>
<View style={styles.imageTextContainer}>
<Image
source={require('./on.png')} />
<Text style={{flex:1 ,color: '#fff',fontSize: 20,marginLeft: 20}} >Home</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.pressLink('About')}>
<View style={styles.imageTextContainer}>
<Image
source={require('./on.png')} />
<Text style={{flex:1 ,color: '#fff',fontSize: 20,marginLeft: 20}} >About</Text>
</View>
</TouchableOpacity>
</View>
const styles = StyleSheet.create({
menuContainer: {
flex: 0.52,
marginLeft: 5
},
imageTextContainer: {
marginLeft: 20,
padding: 10,
flexDirection: 'row',
justifyContent: 'space-between'
}
});