Is it possible to place one <View> over another in react-native? - react-native

I want to place one <View> over another in react-native. Here is my code:
<View style={styles.container}>
<View style={styles.vimgProduct}>
<Image style={styles.imgProduct} source={{uri: "http://www.unclesamsjamms.com/unclesamcash7.jpg"}}/>
</View>
<View style={styles.vNewView}>
</View>
</View>`
and here is my style:
container: {
flex: 1,
paddingTop: 65,
backgroundColor: "#F5FCFF"
},
vimgProduct: {
paddingTop: 20,
justifyContent: 'center',
alignItems: 'center'
},
vNewView: {
height: 400,
paddingVertical: 20,
marginTop: -60,
marginHorizontal: 40,
borderWidth: 3,
borderColor: "black",
borderRadius: 15,
flexDirection: "row",
justifyContent: 'center',
alignItems: 'center'
}
My problem now is, that the View with Image is over my "vNewView" but the border of "vNewView" is in foreground and overlaps my "vimgProduct".
I want that my vNewView is in background and my vimgProduct is in foreground. How can I achieve this? In HTML/CSS it works with zIndex I think.
Could you help me please here? Would be great!
best regards,
Alban

To achieve similar functionality to z-index in react native, you simply need to place your components in the order that they are intended to be layered. For example, if you have three components in a row, then the second will overlay the first, and the third will overlay the second, so on and so forth.
For what you are doing, maybe try placing the vNewView as the first item in the view and use position: 'absolute' .

I'd here is an overlay container that you can use to overlay your views:
import React, { ReactElement } from 'react';
import { View, StyleSheet, ViewStyle, StyleProp } from 'react-native';
type OverlayContainerProps = {
back?: ReactElement;
front?: ReactElement;
backViewStyle?: StyleProp<ViewStyle>;
frontViewStyle?: StyleProp<ViewStyle>;
containerStyle?: StyleProp<ViewStyle>;
};
export default function OverlayContainer({
back,
front,
backViewStyle,
frontViewStyle,
containerStyle,
}: OverlayContainerProps): ReactElement {
return (
<View style={[styles.container, containerStyle]}>
<View style={backViewStyle}>{back}</View>
<View style={[styles.front, frontViewStyle]}>{front}</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
},
front: {
position: 'absolute',
zIndex: 1,
},
});
Credit where it is due, I got my inspiration for this approach from seeing this bit of code: https://github.com/onmyway133/blog/issues/254

Related

How to make triple outline border in React Native

Can anybody tell me how to do this kind of triple border design in React Native?
Wrap 3 different views to get different borders.
import React, { Component } from "react";
import { StyleSheet, Text, View, SafeAreaView } from "react-native";
export default class Example extends Component {
render() {
return (
<SafeAreaView style={styles.container}>
<View style={{ borderWidth: 1, borderRadius: 5, borderColor: 'red', width: "90%" }}>
<View style={{ borderWidth: 1, borderRadius: 10, borderColor: 'green', width: "100%" }}>
<View style={{ borderWidth: 1, borderRadius: 15, borderColor: 'blue', width: "100%" }}>
<Text style={{alignSelf: 'center'}}>Search</Text>
</View>
</View>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 100,
justifyContent: "center",
alignItems: "center"
}
});
This not be the optimal solution. Change this accoding to requirement.
Hope this helps you. Feel free for doubts.

Why does changing my margin percentage mess with the spacing of my custom buttons?

I'm new to React-Native and web development, but I do have a smidge of CSS experience. I've come across an issue that I can't figure out and I haven't found anything online that expresses a similar problem so that I may figure out why this is happening.
I have custom hexagonal buttons that I want to space out in a similar fashion to an onscreen keyboard which I have done, but my buttons are a bit too far up. The first row is obscured by the notification bar. My StyleSheet for my rows look like this:
const style = StyleSheet.create({
screen: {
width: '100%',
height: '100%',
backgroundColor: '#lele19'
},
firstRow: {
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
paddingTop: '5%',
marginHorizontal: '5%'
}
row: {
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
marginHorizontal: '5%'
}
});
Each "row" of buttons is within a View component.
So to try to fix the position so that the notification bar was not in the way I changed my paddingTop: from 5% to 15% and as a result, it seems to move my row down as I want, but now the space between my buttons is increased as seen from this screenshot:
It seems that any padding I do that is past 5% causes the spacing of my buttons to be off. How can I prevent this? What am I doing wrong? It appears this way on any device whether it is a phone or a tablet. Any help is greatly appreciated.
EDIT:
Since people are asking for more here is my PortraitLayout.js:
import React from 'react';
import { View, StyleSheet } from 'react-native';
import HexButton from './HexagonButton';
const PortraitLayout = props => {
return (
<View style={styles.screen}>
<View style={styles.firstRow}>
<HexButton>a</HexButton>
<HexButton>b</HexButton>
<HexButton>c</HexButton>
<HexButton>d</HexButton>
<HexButton>e</HexButton>
<HexButton>f</HexButton>
<HexButton>g</HexButton>
<HexButton>h</HexButton>
<HexButton>i</HexButton>
</View>
<View style={styles.row}>
<HexButton>j</HexButton>
<HexButton>k</HexButton>
<HexButton>l</HexButton>
<HexButton>m</HexButton>
<HexButton>n</HexButton>
<HexButton>o</HexButton>
<HexButton>p</HexButton>
<HexButton>q</HexButton>
<HexButton>r</HexButton>
</View>
<View style={styles.row}>
<HexButton>s</HexButton>
<HexButton>t</HexButton>
<HexButton>u</HexButton>
<HexButton>v</HexButton>
<HexButton>w</HexButton>
<HexButton>x</HexButton>
<HexButton>y</HexButton>
<HexButton>z</HexButton>
</View>
</View>
);
};
const styles = StyleSheet.create({
screen: {
width: '100%',
height: '100%',
backgroundColor: '#1e1e19'
},
firstRow: {
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
paddingTop: '5%',
marginHorizontal: '5%'
},
row: {
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
paddingTop: '5%',
marginHorizontal: '5%'
}
});
export default PortraitLayout;
HexagonButton.js:
import React from 'react';
import { View, StyleSheet, TouchableOpacity, Text, Dimensions } from 'react-native';
const HexagonButton = props => {
return (
<TouchableOpacity>
<View style={styles.hexagon}>
<View style={styles.hexagonInner}>
<Text style={styles.buttonText}>{props.children}</Text>
</View>
<View style={styles.hexagonBefore} />
<View style={styles.hexagonAfter} />
</View>
</TouchableOpacity>
);
};
let buttonWidth = Dimensions.get('window').width / 11; //Make enough room for 16 even though I am only putting 13 per row.
let buttonHeight = buttonWidth * 0.55;
const styles = StyleSheet.create({
hexagon: {
width: buttonWidth,
height: buttonHeight
},
hexagonInner: {
width: '100%',
height: '100%',
backgroundColor: '#ffec33',
justifyContent: 'center',
alignItems: 'center'
},
hexagonAfter: {
position: 'absolute',
bottom: -1 * (buttonHeight * 0.45),
left: 0,
width: 0,
height: 0,
borderStyle: 'solid',
borderLeftWidth: buttonWidth * 0.5,
borderLeftColor: 'transparent',
borderRightWidth: buttonWidth * 0.5,
borderRightColor: 'transparent',
borderTopWidth: buttonHeight * 0.45,
borderTopColor: '#ffec33'
},
hexagonBefore: {
position: 'absolute',
top: -1 * (buttonHeight * 0.45),
left: 0,
width: 0,
height: 0,
borderStyle: 'solid',
borderLeftWidth: buttonWidth * 0.5,
borderLeftColor: 'transparent',
borderRightWidth: buttonWidth * 0.5,
borderRightColor: 'transparent',
borderBottomWidth: buttonHeight * 0.45,
borderBottomColor: '#ffec23'
},
buttonText: {
fontSize: 18
}
});
export default HexagonButton;
and App.js:
import React from 'react';
import { StyleSheet, View } from 'react-native';
import LandscapeLayout from './components/LandscapeLayout';
import PortraitLayout from './components/PortraitLayout';
export default function App() {
return (
<PortraitLayout/>
);
}
const styles = StyleSheet.create({
});
That is literally all of the code I have. I hope this will paint a better picture of the issue. I will try the borders thing and see what that yields.
EDIT:
Here is the result of the border color test. It looks like my buttons extend past the border. For simplicity, I only changed the top row so that the buttons were spaced incorrectly. Also for the sake of testing I added another style to the Portrait.js file that is just a copy of row.
I'm still not sure why it happens but I did manage to fix it. It had something to do with justifyContent and the fact that my button rows were not within a new of their own. I added a view around my button rows like this:
<View style={styles.screen}>
<View style={styles.keyboardLayout}>
<View style={styles.row}>
<HexButton>a</HexButton>
<HexButton>b</HexButton>
<HexButton>c</HexButton>
<HexButton>d</HexButton>
<HexButton>e</HexButton>
<HexButton>f</HexButton>
<HexButton>g</HexButton>
<HexButton>h</HexButton>
<HexButton>i</HexButton>
</View>
<View style={styles.row}>
<HexButton>j</HexButton>
<HexButton>k</HexButton>
<HexButton>l</HexButton>
<HexButton>m</HexButton>
<HexButton>n</HexButton>
<HexButton>o</HexButton>
<HexButton>p</HexButton>
<HexButton>q</HexButton>
<HexButton>r</HexButton>
</View>
<View style={styles.row}>
<HexButton>s</HexButton>
<HexButton>t</HexButton>
<HexButton>u</HexButton>
<HexButton>v</HexButton>
<HexButton>w</HexButton>
<HexButton>x</HexButton>
<HexButton>y</HexButton>
<HexButton>z</HexButton>
</View>
</View>
</View>
const styles = StyleSheet.create({
screen: {
width: '100%',
height: '100%',
backgroundColor: '#1e1e19'
},
row: {
justifyContent: 'space-between',
flexDirection: 'row',
paddingTop: '5%',
marginHorizontal: '5%'
},
keyboardLayout: {
height: '50%',
width: '100%',
alignItems: 'center',
justifyContent: 'flex-end'
}
});
I would still like to know the exact cause, but for now, my problem has been solved.

Why are my buttons running off the screen?

I'm trying to have my two buttons sit in a row, equally spaced, and I want them of equal height and width. But they look like this at the moment.
I'm very new to React Native so please go gently!
Here's my code for what's returned.
return (
<View style={styles.screen}>
<View style={styles.horseProfile}>
<HorseProfile />
</View>
<View style={styles.vitalSignsGrid}>
<LargeVitalSigns />
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={this._alertHandler}>
<View style={styles.buttonStyling}>
<Text style={styles.buttonText}>ECG</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={this._alertHandler}>
<View style={styles.buttonStyling}>
<Text style={styles.buttonText}>Resp Pattern</Text>
</View>
</TouchableOpacity>
</View>
<View>{/* timer and stop button */}</View>
</View>
)
Here are my styles.
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
horsePatientProfile: {
flex: 1
},
vitalSignsGrid: {
flex: 3,
backgroundColor: '#14172B'
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: 'green',
width: '100%',
flex: 4
},
buttonStyling: {
backgroundColor: '#2B4250',
borderRadius: 30,
alignItems: 'center',
justifyContent: 'space-around',
width: '50%',
height: '35%',
flexDirection: 'row',
},
buttonText: {
color: '#84C5C6',
fontWeight: 'bold'
}
})
Can anyone help please? Thank you.
the width of your buttons styles.buttonStyling is 50% which is 50% of the parent Component, the parent is the touchableOpacity, since it doesn't have a set width itself it will stretch with the content, in other words the 50% does not mean the same thing, you should give an exact (relative size, I like react-native-size-matter) to the touchable opacity and justifyContent as space between to space evenly
For height, width try using React Native Dimensions React Native Dimentions
Import it:
import {Dimensions} from "react-native";
var {height, width} = Dimensions.get('window');
Example using in style:
buttonStyling: {
backgroundColor: '#2B4250',
borderRadius: 30,
alignItems: 'center',
justifyContent: 'space-around',
width: width/2,
height: height / 3.5,
flexDirection: 'row',
},
or use Flexbox

TextInput full view in row direction

I ma new to React native development. In my application I have login screen. In laogin screen I have two text inputs along with images. I have taken image and Text input in one view and given flex direction as row. And I have given text input as alignSelf stretch. So here my issue is I need full length of text input along with image. But if I removed flex direction then will get full length of the screen. The following is the code
import React, {Component} from 'react';
import {StyleSheet, Text, View,TextInput,TouchableOpacity,StatusBar,Image} from 'react-native';
export default class App extends Component {
static navigationOptions = {
title: "Welcome",
header: null,
}
render() {
// const { navigate } = this.props.navigation
return (
<View style={styles.container}>
<StatusBar
barStyle="light-content"
backgroundColor="#2f5597"
/>
<Image source={require('../../app/images/ic_accountlist.png')} style={styles.logo}/>
<View style={styles.loginView}>
<View >
<Image source={require('../../app/images/ic_userid.png')} />
<TextInput placeholder="Acct No/User Id" style={styles.textInput} underlineColorAndroid={'rgb(0,0,0)'}></TextInput>
</View>
<View style={styles.user}>
<Image source={require('../../app/images/ic_password.png')} />
<TextInput placeholder="Password" style={styles.textInput} underlineColorAndroid={'rgb(0,0,0)'}></TextInput>
</View>
</View>
<TouchableOpacity style={styles.btnLogin} onPress={this.login}><Text style={{color: 'white'}}>Log In</Text></TouchableOpacity>
</View>
);
}
login=()=>{
// alert("testing......");
this.props.navigation.navigate('Profile');
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCF0',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
color:'#FF0000',
},
textInput: {
alignSelf: 'stretch',
padding: 10,
marginLeft: 5,
marginRight:0,
},
btnLogin:{
borderRadius: 10,
backgroundColor: '#2f5597',
padding: 10,
marginTop: 20,
paddingLeft: 50,
paddingRight: 50,
alignSelf: 'center',
},
user:{
flexDirection: 'row',
},
logo :{
marginTop: 100,
alignSelf: 'center',
},
loginView:{
marginTop: 60,
}
});
And the following is the output I am getting
And here I need the text input full along with image. Like the below
There is no need to use the alignSelf property. Instead, you have to use flex: 1:
textInput: {
flex: 1,
padding: 10,
marginLeft: 5,
marginRight: 0,
},
flex: 1 is a shorthand notation, so you could also use explicitly flexGrow: 1 to achieve the same effect:
textInput: {
flexGrow: 1,
padding: 10,
marginLeft: 5,
marginRight: 0,
},
You can read more about flex on MDN.
Result (ignore the different icon):
You need to add flex: 1 to textInput style
textInput: {
alignSelf: 'stretch',
padding: 10,
marginLeft: 5,
marginRight:0,
flex: 1
}

react native,child's width by percentage

Here is my code. I want the product view to take up 90% width of its parent. However, the settings below are not working.
...any idea how to achieve it without using dimensions?
return (
<LazyloadScrollView
style={styles.container}
contentContainerStyle={styles.content}
name="scrollImage" >
{list.map((product, i) => <View key={i} style={styles.product}>
<LazyloadImage
host="scrollImage"
style={styles.image}
source={image}
animation={false}>
<View style={styles.id}>
<Text style={styles.idText}>{product.id}</Text>
</View>
</LazyloadImage>
</View>)
}
</LazyloadScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ffffff'
},
content: {
paddingTop: 20,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#eee'
},
product: {
flex: 0.9,
marginTop: 5,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#FFFFFF'
},
Why not use Dimensions? It will enable your app to be responsive.
If you don't want to use dimensions, try some style settings in the container and it's children, for example, make it full width with padding
container: {
backgroundColor: '#ffffff',
alignSelf: 'stretch',
padding: 30
}
I don't know if it works because you would have to post the rest of the code to test it but keep playing with the style and flex properties until you make it work, shouldn't take long.
Btw, always good to revisit the official layout props docs from react native
And css tricks guide to flexbox