I'm experiencing a lot of difficulty trying to implement a "double modal", i.e. two modals at the same time.
e.g.
I'm using Overlay from the 'react-native-elements' library to achieve the modal effect, however, putting two of them together in a view isn't working as it will only display the first one. I'm also finding that directly setting the height of the overlay isn't having any effect.
I then considered creating a custom component but can't figure out how to dim the background using CSS.
If you want, change the your element modal to react-native-modal. Keep try and execute the below code. I hope it'll work for you.
import Modal from 'react-native-modal';
const [isModalVisible, setModalVisible] = useState(false);
const toggleModal = () => {
setModalVisible(!isModalVisible);
};
<TouchableOpacity onPress={toggleModal}>
<Text>Button Text</Text>
<Modal
isVisible={isModalVisible}
onBackdropPress={() => setModalVisible(false)}>
<View style={{ backgroundColor: 'white', padding: 20, height:250 }}>
<Text>First box content appear here</Text>
</View>
<View style={{ backgroundColor: 'white', padding: 20, height:100, marginTop: 30 }}>
<Text>Second box content appear here</Text>
</View>
</Modal>
</TouchableOpacity>
Related
When attempting to use ScrollView it appears to not respect justifyContent of its parent container.
import React from 'react';
import { Text, ScrollView, StyleSheet, TextStyle, View, ViewStyle } from 'react-native';
interface TODO_TextCard {
text: string,
}
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
<ScrollView>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
</View>;
}
const styles = StyleSheet.create({
quoteTextStyle: {
fontSize: 30,
fontStyle: 'italic'
} as TextStyle,
viewStyle: {
flex: 1,
borderWidth: 2, borderColor: 'red',
justifyContent: 'center',
paddingHorizontal: 10
} as ViewStyle,
});
<TODO_TextCard text={'The mind adapts and converts to its own purposes the obstacle to our acting. The impediment to action advances action. What stands in the way becomes the way'}/>
Rendered as:
Now if I remove the and just render text such as
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</View>;
}
The Text element does respect the justifyContent:center of the parent and renders as:
Is it possible for Scroll view to be centered?
The solution that I have in mind right now is to check the length of the text and conditionally render Scroll View something like:
/** This some text length would have to be different depending on the device screen, and
* even with different device screens would still not work all the time if the text
* can have new lines in it.*/
const SOME_TEXT_LENGTH = 300;
export const TODO_TextCard: React.FunctionComponent<TODO_TextCard> = (props: TODO_TextCard) => {
return <View style={styles.viewStyle}>
{props.text.length > SOME_TEXT_LENGTH ?
<ScrollView>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
:
<Text style={styles.quoteTextStyle}>{props.text}</Text>
}
</View>;
}
Which very much is not ideal, due to different device screens as well as text potentially having new lines.
The ScrollView does in fact respect the justifyContent:center of its parent. The ScrollView is placed in the center of the outer View component. But here the ScrollView takes up the whole vertical screen, so it seems like it is not centered.
Try setting <ScrollView style={{backgroundColor: 'green'}}> to see what i mean.
Try applying viewStyle or a similar styling to the ScrollView itself. Make sure that you use the attribute contentContainerStyle instead of style. This snippet works for me.
<View style={styles.viewStyle}>
<ScrollView contentContainerStyle={{flex: 1, justifyContent: 'center'}}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
</View>
I also found this article. Maybe it will also help you out.
You need to give styling to ScrollView, for styling ScrollView you can use style or contentContainerStyle prop:
style defines the outer container of the ScrollView, e.g its height and relations to siblings elements
contentContainerStyle defines the inner container of it, e.g items alignments, padding, etc
In your case you need to give contentContainerStyle to position your items for eg:
return (
<View style={styles.viewStyle}>
{props.text.length > SOME_TEXT_LENGTH ?
<ScrollView
contentContainerStyle={{
flex: 1, //To take full screen height
justifyContent: 'center',
alignItems: 'center,
}}>
<Text style={styles.quoteTextStyle}>{props.text}</Text>
</ScrollView>
:
<Text style={styles.quoteTextStyle}>{props.text}</Text>
}
</View>
);
Like the title says, I want to ask if there's a way to create a button with gradient color and an icon in React Native? I know that gradient color can't be added without an external library, so I tried this one:
https://www.npmjs.com/package/react-native-gradient-buttons
However, I can't see a way to add Icon as a props to the gradient buttons of this library. The answer doesn't have to use the library, I would just like to know a convenient way to achieve the button I described. Thanks.
You can create your own button with an icon like below
import { Ionicons } from '#expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
const GradientButton = ({ onPress, style, colors, text, renderIcon }) => {
return (
<TouchableOpacity onPress={onPress}>
<LinearGradient colors={colors} style={style}>
{renderIcon()}
<Text style={styles.text}>{text}</Text>
</LinearGradient>
</TouchableOpacity>
);
};
Usage would be
<GradientButton
onPress={() => alert('Button Pressed')}
style={{
padding: 15,
alignItems: 'center',
borderRadius: 5,
flexDirection: 'row',
}}
colors={['#874f00', '#f5ba57']}
text="Press"
renderIcon={() => (
<Ionicons
name="md-checkmark-circle"
size={20}
color="green"
style={{ marginHorizontal: 20 }}
/>
)}
/>
You will have more control over the button and change it anyway you want, you can add more props to customize it the way you want.
You can try out the demo here
https://snack.expo.io/#guruparan/gradientbutton
The above icon and gradient packages are for expo
You can use RN Vector icons and Linear gradient package as well
In the docs of the package you provided it shows an example like this:
<GradientButton
style={{ marginVertical: 8 }}
textStyle={{ fontSize: 20 }}
gradientBegin="#874f00"
gradientEnd="#f5ba57"
gradientDirection="diagonal"
height={60}
width={300}
radius={15}
impact
impactStyle='Light'
onPressAction={() => alert('You pressed me!')}
>
Gradient Button #2
</GradientButton>
Maybe try adding your icon in between the tags instead of as prop?
I have 8 buttons which i would like to align in horizontal row, side by side. everything i have tried hasn't worked and the just display one on top of another.
Here's what i have at the mo.
Thanks
categories: ['art', 'funny', 'inspire', 'life', 'love', 'management', 'sports', 'students'],
render() {
let cat = this.state.categories.map((value, key) => {
return (
<View style={styles.catButtons}>
<TouchableOpacity
style={styles.buttonContainer}
key={key}
activeOpacity={0.7}
>
<Button style={styles.button}
color={'darkslategrey'}
key={key}
title={value}
onPress={() => { this.getCategoryQuote(value) }}
/>
</TouchableOpacity>
</View>
)
})
return (
<View>
{cat}
</View>
)
}
const styles = StyleSheet.create({
catButtons: {
flexWrap: 'wrap'
},
buttonContainer: {
width: 125,
margin: 10
},
});
I think, in this case, the flex items are the buttons. But the problems lies in the flex container: TouchableOpacity.
As your code suggest, there is one flex container for one button, and that is repeated by the map function.
It should be one flex container for all flex items (buttons). That means, the flex container should be outside of your map function and the items directly as its children (that are mapped by the map function).
I am trying to center an Image within a View both horizontally and vertically the problem is that no matter what I put in the code it still seems to be in the same position all the time. I have this code for another View from another screen and it's exactly how I need it to be, however for the other pages it's not responding.
Here is my code:
<View style={styles.header}>
<Icon
raised
name='chevron-left'
type='octicon'
color='#f50'
onPress={() => this.props.navigation.goBack()}
containerStyle={{ alignSelf:'flex-end', marginRight:20, marginTop:-60 }}/>
<Image source={Logo} style={{resizeMode:'stretch', width:50, height:50, alignItems:'center', marginTop:30, position:'absolute'}}/>
</View>
const styles = StyleSheet.create({
header:{
backgroundColor:'#ff4714',
height:SCREEN_HEIGHT/8,
flexDirection: 'row'
}
});
EDIT: I've removed all the styling for the <Image> except for width and height and the image stays at the same place. I don't know what to make of this
Here is an expo snack https://snack.expo.io/SyCO!ree8
You need to add justifyContent:'center' and alignSelf:'center' to your image style,
Just check the code :
<View style={{
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
}}>
<Image source={{uri:'https://source.unsplash.com/random'}} style={{height:50,width:50,alignSelf:'center'}} />
</View>
And this is expo snack : expo-snack
UPDATE:
HERE IS MY UPDATED EXPO SNACK:
check here
Hope it helps
Try adding:
alignItems: 'center',
justifyContent: 'center'
to your header style
You might also need to add flex:1, depending on the state of your View
I am trying to achieve dynamic padding top and bottom. I am aware that paddingTop and paddingBottom with % will use the width of the container and I am fine with that.
Unfortunately when I do set the paddingTop to any value with %, it sets the paddingBottom to the same value. Basically paddingTop: '5%', paddingBottom: '0%' will give me equal 5% paddings on both sides.
If I set paddingBottom to any % value - it's just being added to the value that came form the top. So: paddingTop: '5%', paddingBottom: '10%' results in paddingBottom equal to 15%...
I checked the same solution in a web project and there it works as expected.
The snack presenting the problem:
https://snack.expo.io/BJ9-2t8LB
The problem is on both Android and iOS.
How to solve it?
Apply the value to the child container to be applied, not to the parent container.
I have modified the answer according to the conditions you want. You should send Bottom's territory to the parent's container. Because they interact with each other in their child's container, they must be independent.
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={styles.wrapper}>
<View style={styles.inner}>
<View style={{ backgroundColor: 'yellow' }}>
<Text>TOP</Text>
</View>
</View>
<View style={{ backgroundColor: 'red', }}><Text>BOTTOM</Text></View>
</View>
);
}
}
const styles = StyleSheet.create({
wrapper: {
flex:1,
paddingLeft: 24,
paddingRight: 24,
backgroundColor: 'green',
paddingBottom:"5%"
},
inner: {
flex:1,
justifyContent: 'space-between',
backgroundColor: 'blue',
marginTop:"10%"
},
});
That is strange behavior, you should bring it up as an issue to react-native.
In the meantime, a workaround would be applying marginTop and marginBottom to the inner View, instead of paddingTop and paddingBottom to the wrapper View.
const styles = StyleSheet.create({
ayz:{
marginTop:"15%",
backgroundColor:'pink',
alignItems:'center',
justifyContent:'center',
},
asd:{
color:'white',
fontSize:50,
fontWeight:'bold'
}
});