I'm trying to have a popup dialog (created as a component with position: 'absolute') and to close it when user clicks outside of the popup.
I'm new to React Native so other things I did might be wrong, forgive me for that :)
This is a screenshot of the popup when it is open
This is some of the code:
From the Popup component:
render() {
if (!this.props.open) {
return <View />
}
return (
<View style={styles.container}>
<View style={styles.popupStyle}>
<View style={{flex:1, justifyContent: 'center', marginRight: 10}}>
<View style={styles.amountEnterStyle}>
<TextInput
keyboardType={'numeric'}
underlineColorAndroid='transparent'
autoCorrect={false}
style={styles.textInputStyle}
value={this.state.amount}
onChangeText={this._onAmountEnter.bind(this)} />
<Text style={styles.currencyTextStyle}>NIS</Text>
</View>
<View style={styles.separatorStyle} />
<View style={styles.categorySectionStyle}>
{this._renderCategoryDropdown()}
</View>
</View>
<View style={{justifyContent: 'center'}}>
<TouchableWithoutFeedback
onPress={this._onAddPaymentClicked.bind(this)} >
<View style={{width: 110, height:100, backgroundColor: "#ff0000"}} />
</TouchableWithoutFeedback>
</View>
</View>
</View>
);
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
width: undefined,
height: undefined,
justifyContent: 'center',
alignItems: 'center',
},
amountEnterStyle: {
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row'
},
textInputStyle: {
width: 100,
fontSize: 50,
fontWeight: 'bold',
height: 65,
flex: 1,
marginTop: -20,
paddingBottom: 0,
marginBottom: 0,
marginLeft:10,
textAlignVertical: 'center'
},
currencyTextStyle: {
fontSize: 50,
color: '#c0c0c0',
marginTop: -20,
textAlignVertical: 'center'
},
separatorStyle: {
height: 2,
marginTop: 0,
backgroundColor: '#c0c0c0',
},
categorySectionStyle: {
justifyContent: 'flex-start',
flexDirection: 'row',
alignItems: 'flex-start',
marginTop: 8
},
categoryColorDotStyle: {
width: 20,
height: 20,
borderRadius: 100/2,
marginLeft: 10,
marginTop: 5,
},
categoryTextStyle: {
fontSize: 24,
marginHorizontal: 4,
color: '#c0c0c0',
marginLeft: 10,
paddingRight: 10,
marginTop: -3
},
popupStyle: {
width: Dimensions.get('window').width - 60,
flexDirection: 'row',
justifyContent: 'space-between',
height: 150,
paddingRight:10,
paddingLeft:10,
borderRadius: 2,
margin: 20,
padding: 10,
opacity: 1,
borderRadius: 10,
backgroundColor: '#ffffff'
},
dropdownSeparator: {
height: 1,
backgroundColor: 'cornflowerblue'
},
And this is the hosting component:
render() {
var totalIncome = this.props.balance.totalIncome;
var totalExpanses = this.props.balance.totalExpanses;
return (
<View style={{flex:1, justifyContent: 'space-between'}}>
<Image pointerEvents='none' source={require('../../res/background.png')} style={styles.container} />
<MainScreenHeader onSettingPress={this._onBalanceSettingsPress.bind(this)}/>
<MainBalanceCounter totalCount={totalIncome} currentCount={totalIncome-totalExpanses} />
<View style={{justifyContent: 'center', alignItems: 'center', marginBottom: 150}}>
<AddPaymentButton onPress={this._onAddPaymentPress.bind(this)} />
<PaymentPopup
open={this.state.paymentPopupOpen}
onAddPaymentClicked={this._onPaymentPopupAddClicked.bind(this)} />
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
width: undefined,
height: undefined,
backgroundColor:'transparent',
justifyContent: 'center',
alignItems: 'center',
},
innerContainer: {
justifyContent: 'space-around',
alignItems: 'center',
flex: 1,
backgroundColor: 'transparent'
},
});
I was trying man things to have a view that will catch clicks that happens outside of the popup, but no success.
Any help will be much appreciated,
Thanks,
Giora.
have you tried out react-native-modalbox? I use it in my applications and it works pretty great. If you have touch events behind the modal, it will close. Also, you can define how large you'd like the modal to be. It doesn't have to take up the whole screen.
Otherwise, you were on the right track. You'd need a TouchableWithoutFeedback component that covers the full width and height of the screen. Your popup would be alongside of this component with a higher zIndex. Let me know if you'd like to go this route and I can provide more advice. Cheers!
Related
I have a problem and would like some help. I want to create button with right arrow that moves. But unfortunately the arrow starts to move from the beginning of the button itself. I only want to move that arrow at the right side. So for now it looks like that
I think it's happening because animation is affected from button container!
So my code so far -
<TouchableOpacity
style={{
position: "absolute",
bottom: 40,
paddingVertical: 10,
paddingHorizontal: 15,
justifyContent: "center",
width: "40%",
borderRadius: 20,
flexDirection: "row",
backgroundColor: "#a12f2f",
alignItems: "center",
textAlign: "center"
}}
activeOpacity={0.9}
onPress={() => onPressNext(count)}
>
<Text style={{ fontSize: 16,color: "white", marginRight: 10,}}>
{count === 0 ? "Explain steps" : "Next step"}
</Text>
{count === 0 && (
<Animatable.View
animation={"slideInLeft"}
iterationCount={"infinite"}
>
<VectorIconComponent
size={20}
name={"arrowright"}
color={"white"}
type={ICON_TYPES.AntDesign}
/>
</Animatable.View>
)}
</TouchableOpacity>
Also I used react-native-animatable to create that animation. So my question is how can I make this animation without crossing the text?
Try this !
import React, { useEffect } from 'react'
import { Animated, SafeAreaView, View, Text, TouchableOpacity, Image, Easing } from 'react-native'
export default function App() {
const animatedValue = new Animated.Value(0)
useEffect(() => {
_start()
}, [animatedValue])
function _start() {
const toValue = 35
Animated.loop(
Animated.timing(animatedValue, {
toValue,
duration: 1000,
useNativeDriver: true
})
).start()
}
function handlePress() {
alert('ok')
}
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<TouchableOpacity
activeOpacity={0.75}
style={{ position: 'absolute', bottom: 20, height: 60, width: 200, backgroundColor: 'tan', alignSelf: 'center', borderRadius: 20, flexDirection: 'row' }}
onPress={handlePress}>
<View style={{ height: 60, width: 140, alignItems: 'center', justifyContent: 'center', }}>
<Text>
Explain Steps
</Text>
</View>
<View style={{ height: 60, width: 60, justifyContent: 'center', }}>
<Animated.View
style={{ height: 30, width: 30, transform: [{ translateX: animatedValue }] }}>
<Image
source={{ uri: 'https://cdn.iconscout.com/icon/free/png-256/right-arrow-1438234-1216195.png' }}
style={{ height: '100%', width: '100%' }}
/>
</Animated.View>
</View>
</TouchableOpacity>
</View>
</SafeAreaView>
)
}
Output
I am trying to make an element with style={styles.settingsButtonContainer} not to depend on position of other elements on the view, but to be always in the top right corner of the screen. I am trying in this way:
<View style={styles.container}>
<RCActivityIndicator animating={showActivityIndicator} />
<RCModal title={alertTitle} visible={alertVisible} onButtonPress={alertOnPress} />
<ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}>
<Text style={styles.title}>Noughts and Crosses</Text>
<Text style={styles.tip}>Get {winCondition()} in row, column or diagonal</Text>
<TouchableHighlight underlayColor="#000000" style={[styles.button, styles.newGameButton]} onPress={setInitialFieldState}>
<Text style={styles.buttonText}>New game</Text>
</TouchableHighlight>
<Text style={styles.turnContainer}>Turn: <Text style={[styles.turn, { color: turn === 'X' ? '#2E86C1' : '#E74C3C'}]}>{turn}</Text></Text>
<Field state={fieldState} size={fieldSize} winner={winCombination} onCellPress={onCellPress} />
</ScrollView>
<View style={styles.settingsButtonContainer}>
<TouchableHighlight underlayColor={theme.colors.secondary} style={styles.settingsButton} onPress={onSettingsPress}>
<Image source={require('../img/settings.png')} style={styles.settingsIcon} />
</TouchableHighlight>
</View>
</View>
const styles = StyleSheet.create({
container: {
flex: 1
},
title: {
textAlign: 'center',
fontSize: 33,
fontFamily: theme.fonts.primary,
color: theme.colors.text
},
button: {
alignItems: 'center',
padding: 5,
margin: 5,
marginLeft: 10,
marginRight: 10,
borderRadius: 20,
height: 35,
justifyContent: 'center'
},
newGameButton: {
backgroundColor: theme.colors.primary,
paddingLeft: 15,
paddingRight: 15,
},
buttonText: {
fontSize: 25,
fontFamily: theme.fonts.primary,
color: theme.colors.text
},
tip: {
textAlign: 'center',
fontSize: 25,
marginLeft: 10,
marginRight: 10,
fontFamily: theme.fonts.primary,
color: theme.colors.text
},
turnContainer: {
textAlign: 'center',
fontSize: 33,
fontFamily: theme.fonts.primary,
color: theme.colors.text,
marginLeft: 10,
},
turn: {
fontSize: 30,
fontFamily: theme.fonts.noughtsAndCrosses,
},
privacy: {
textAlign: 'center',
color: theme.colors.secondaryText,
fontSize: 15,
textDecorationLine: "underline",
marginTop: 20
},
settingsButtonContainer: {
position: 'absolute',
top: 5,
right: 5,
height: 50,
width: 50,
alignSelf: 'flex-end',
},
settingsButton: {
height: 50,
width: 50,
borderRadius: 25,
},
settingsIcon: {
height: 50,
width: 50
},
settings: {
marginTop: 30
},
buttonsContainer: {
flexDirection: 'row',
alignItems: 'center'
}
});
But it just takes a full row for itself, so the ScrollView doesn't take 100% height. How to make it work?
try to wrap the settingsButtonContainer
and use
settingButtonContainerWrapped: {
alignItem: 'flex-end',
flexDirection : 'row',
},
Actually the issue was in another element, that was on top of the ScrollView - it was RCActivityIndicator who took this place. I styled it, and it worked.
Use css:
[eleSelector] {
position: absolute;
right: 0;
top: 0;
}
Check HTML element Selector in CSS
I have a simple textbox to which i have given an outline. However, If you look closely you will see that the border and the border outline dont match. The white color of the View extends out of the border outline as well. How can I fix this?
export const AddressTextBox: React.FunctionComponent<AddressTextBoxProps> = ({
placeName,
}) => {
return (
<View style={styles.textBox}>
<Text style={styles.text}>{placeName}</Text>
</View>
);
};
export const styles = StyleSheet.create({
textBox: {
backgroundColor: 'white',
height: moderateScale(50),
width: '70%',
marginTop: moderateScale(40),
alignSelf: 'center',
borderRadius: moderateScale(20),
borderColor: '#383838',
borderWidth: 0.3,
alignItems: 'center',
flexDirection: 'row',
},
text: {
fontSize: moderateScale(13),
flex: 1,
marginHorizontal: 10,
textAlign: 'center',
},
});
Edit:
The problem doesn't exist in iOS simulator but does occur in Android phones.
I try with this and without moderateScale and it works fine
<View style={{ flex: 1, backgroundColor: 'pink' }}>
<View
style={{
backgroundColor: 'white',
height: 50,
width: '70%',
marginTop: 40,
alignSelf: 'center',
borderRadius: 20,
borderBottomColor: 'red',
borderTopColor: 'red',
borderRightColor: 'red',
borderLeftColor: 'red',
borderWidth: 0.3,
alignItems: 'center',
flexDirection: 'row'
}}>
<Text
style={{
fontSize: 13,
flex: 1,
marginHorizontal: 10,
textAlign: 'center'
}}>
{'vergaminol'}
</Text>
</View>
</View>
Trying to bring a button.js component to the front of my background carousel. Tried using zIndex, worked fine with my logo but not with my button?
Button code:
return (
<View style={styles.buttonContainer} >
<TouchableOpacity onPress={onPress} style={buttonStyle} >
<Text style={textStyle} >
{children}
</Text>
</TouchableOpacity>
</View>
);
const styles = {
buttonContainer: {
zIndex: 999,
alignItems: 'center'
},
buttonStyle: {
zIndex: 999,
position: 'absolute',
bottom: -200,
flex: .3,
alignSelf: 'auto',
backgroundColor: '#ffff00',
borderRadius: 10,
borderWidth: 1,
borderColor: '#000000',
marginLeft: 5,
marginRight: 5,
width: 250,
borderWidth: 1
},
textStyle: {
zIndex: 999,
alignSelf: 'center',
color: '#000000',
fontSize: 16,
fontWeight: '600',
paddingTop: 10,
paddingBottom: 10
}
};
export default Button;
Code for my app. Notice how i have literally added zIndex 999 for my button, and it still has not worked.
export default function App() {
return (
<View style={styles.carouselContainer}>
<BackgroundCarousel images={images}>
<View style={styles.logoContainer}>
<Image source={logo} style={styles.logo} />
<Text style={styles.logoText}>Hello World</Text>
</View>
<View>
<Button style={{ zIndex: 999 }}>
Let's Get Started
</Button>
</View>
</BackgroundCarousel>
</View>
);
}
const styles = StyleSheet.create({
carouselContainer: {
zIndex: 1,
height: "100%",
width: "100%",
backgroundColor: '#fff',
flex: 1
},
logoContainer: {
zIndex: 2,
alignItems: 'center',
position: 'absolute',
justifyContent: "center",
top: 0, left: 0, right: 0, bottom: 450
},
logo: {
zIndex: 2,
width: 125,
height: 125,
},
logoText: {
zIndex: 2,
color: 'black',
fontSize: 25,
fontWeight: '500',
borderColor: 'white',
fontFamily: "Baskerville-Bold",
},
button: {
flex: 1,
zIndex: 999,
}
});
Basically, is there another way to bring the button forward? Seeing as how zIndex is not working for me in this case.
z-index is only relative to that element's parent so as mentioned by #prakash-karena delete the view that surrounding your button.
<View style={styles.carouselContainer}>
<BackgroundCarousel images={images}>
<View style={styles.logoContainer}>
<Image source={logo} style={styles.logo} />
<Text style={styles.logoText}>Hello World</Text>
</View>
<Button style={{ zIndex: 999 }}>
Let's Get Started
</Button>
</BackgroundCarousel>
</View>
I believe zIndex is supported in the latest version of react native for iOS only, order that you place the elements in determines its layout order. you can try making overflow visible of scrollview.
I'm trying to imitate the image.
I'm having a problem with the button with the like in the middle I can not imitate it.
Since I read it seems that native react on android has a problem with overflow.
I thought you could use a:
marginTop: -25
but it does not seem to solve the problem.
Some advice?
Link expo: https://snack.expo.io/Hk1yUyzB7
Code:
import React, { Component } from 'react';
import { View, StyleSheet, Image, Text } from 'react-native';
//import ViewOverflow from 'react-native-view-overflow';
export default class App extends Component {
render() {
var account = (
<View>
<View
style={{
paddingTop: 20,
paddingLeft: 20,
flexDirection: 'row',
}}>
<Image
style={{ width: 50, height: 50, borderRadius: 25 }}
source={{
uri:
'http://www1.pictures.zimbio.com/bg/Number+Four+World+Premiere+h5-FoI0M8-gl.jpg',
}}
/>
<View
style={{
paddingLeft: 20,
}}>
<Text>Yulia James</Text>
<Text
style={{
color: '#ccc',
}}>
6 hrs ยท IIT London
</Text>
</View>
</View>
<Text
style={{
paddingTop: 20,
paddingLeft: 20,
paddingBottom: 20,
}}>
Making everyday worth it :)
</Text>
<View
style={{
paddingBottom: 20,
}}>
<Image
style={{
width: '100%',
height: 200,
}}
source={{
uri:
'http://www.wordzz.com/wp-content/uploads/2016/11/Night-Ratri.jpg',
}}
/>
</View>
</View>
);
var com = (
<View
style={{
backgroundColor: 'rgba(230,230,230,0.8)',
//height: 40,
alignItems: 'center',
//justifyContent: 'center',
padding: 5,
flex: 1,
}}>
<Text
style={{
color: '#ccc',
fontSize: 18,
}}>
Comment
</Text>
</View>
);
return (
<View
style={{
flex: 1,
backgroundColor: '#e7eff0',
}}>
<View
style={{
backgroundColor: 'rgba(255,255,255,0.8)',
marginTop: 50,
borderTopWidth: 1,
borderBottomWidth: 1,
borderColor: '#e7e7e7',
}}>
{account}
<View
style={{
backgroundColor: '#fff',
borderTopWidth: 1,
borderColor: '#ccc',
//alignItems: 'center',
//justifyContent: 'center',
}}>
<View style={styles.container2}>
{com}
<View
style={{
//backgroundColor: '#000',
borderRadius: 40,
height: 80,
width: 80,
alignItems: 'center',
justifyContent: 'center',
borderColor: '#ccc',
borderWidth: 1,
}}>
<Image
style={{
//resizeMode: 'cover',
height: 40,
width: 40,
}}
source={{
uri: 'http://i.imgur.com/k5jMsaH.gif',
}}
/>
</View>
{com}
</View>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container2: {
flexDirection: 'row',
},
});