react native 2 colors as background - react-native

I'm trying to make 2 colors of background using flex, and it seems to work good but I want to make the button on the middle as in the photo, where I need to insert the button in the code?
i want it to be like this:
return (
<View style={container}>
<View style={leftContainer}>
</View>
<View style={rightContainer}>
</View>
<Button
title="button"/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection:'row'
},
leftContainer:{
flex:1,
backgroundColor: '#ca8afa',
},
rightContainer:{
flex:1,
backgroundColor: '#96d0e3'
},
addButton: {
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
bottom: 20,
right: 20,
zIndex: 1111,
width: calcSize(192 / 2),
height: calcSize(192 / 2)
}
})
the problem is that the button is also in the row now and not in the middle,
how can i fix it?

Here's a live demo of a possible solution: https://snack.expo.io/HJFL7A3ez
Edit - Adding the code here as well:
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<View style={styles.leftContainer}>
</View>
<View style={styles.rightContainer}>
</View>
<View style={styles.buttonContainer}>
<Button style={styles.addButton} title="button"/>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection:'row'
},
leftContainer:{
flex:1,
backgroundColor: '#ca8afa',
},
rightContainer:{
flex:1,
backgroundColor: '#96d0e3'
},
buttonContainer: {
position: 'absolute',
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
},
addButton: {
zIndex: 1111,
width: 200
}
})

Related

Why is my modal height taking up half of the screen?

My modal -- noDevicesModalContainer -- is taking up an enormous amount of the screen and I can't work out why.
I am very new to React Native and web development generally, so please do not be afraid to overexplain!
Thank you in advance for your suggestions.
class DevicesEmptyScreen extends Component {
render() {
return (
<View style={styles.screen}>
<View style={styles.noDevicesImage}>
<Image
source={require('./../../../android/app/src/main/res/drawable/no_devices.png')}
/>
</View>
<View style={styles.noDevicesTextContainer}>
<Text style={styles.noDevicesText}>You do not have any devices yet</Text>
</View>
<View style={styles.noDevicesModalContainer}>
<Text style={[styles.noDevicesText, styles.noDevicesModalText]}>
In case no devices have been assigned, please contact your administrator
</Text>
</View>
</View>
)
}
}
export default DevicesEmptyScreen
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
noDevicesImage: {
flex: 1,
marginTop: 40
},
noDevicesTextContainer: {
flex: 1,
justifyContent: 'center'
},
noDevicesText: {
color: '#89C7C8',
padding: 10
},
noDevicesModalContainer: {
flex: 1,
backgroundColor: '#EBF5F6',
borderRadius: 10,
marginHorizontal: 30,
marginVertical: 30
},
noDevicesModalText: {
marginLeft: 20
}
})
As per Modal documentation. Try this
<Modal transparent={true}
visible={this.state.isVisible}
onRequestClose={this.closeModal}>
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'}}>
<View style={{
width: 300,
height: 300}}>
...
</View>
</View>
</Modal>

React Native. How to place two Text with different fontSize in row with vertical align center

I need to align two Text component with different fontSize in a row and vertically centered. I have following now https://snack.expo.io/#troublediehard/dmVuZ2
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.row}>
<Text style={styles.text1}>Font size 20</Text>
<Text style={styles.text2}>Font size 14</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
row: {
flexDirection: 'row',
backgroundColor: 'red',
},
text1: {
fontSize: 20,
backgroundColor: 'blue',
},
text2: {
fontSize: 14,
backgroundColor: 'green',
},
});
For anyone that didn't found a solution yet, you have to wrap the text within another Text tag:
<View style={styles.container}>
<View style={styles.row}>
<Text>
<Text style={styles.text1}>Font size 20</Text>
<Text style={styles.text2}>Font size 14</Text>
</Text>
</View>
</View>
You need to add alignItems: 'center' to styles.row
row: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'red',
},

How to have elements automatically relocate themselves when one element changes its size in react native?

I currently have a multiline textInput that automatically expands and a button below it. The problem is that the button's location seems to be fixed, it doesn't move down and textInput would just run over it.
Everything is wrapped in a KeyboardAvoidingView:
<KeyboardAvoidingView
style={styles.container}
behavior="padding">
<StatusBar barStyle="light-content"/>
<Text style={styles.title}>{this.state.form.prompt}</Text>
<View style={styles.simpleContainer}>
{this._renderForms()}
<View style={[styles.forwardButtonLocation, styles.indentLeft]}>
<ForwardButton
onButtonPress={this._submitInfo}
/>
</View>
</View>
<View style={{flex: 1, justifyContent: 'flex-end', alignItems: 'flex-end',}}>
<SkipButton
onButtonPress={this._nextState}
/>
</View>
</KeyboardAvoidingView>
this._renderForms() renders the corresponding form for each state, in this case, it renders:
<View style={styles.simpleContainer}>
<AutoExpandingTextInput
style={styles.textContentDark}
placeholder={this.state.form.userInput}
placeholderTextColor={DARK_THEME_CONTENT_COLOR_SECONDARY}
onChangeText={(userInputValue) =>
//TODO: Saving text to nested userInput is causing problem, temporarily save it to userInputValue
//this.setState({form: {...this.state.form, userInput: text}}
this.setState({userInputValue}
)}
/>
</View>
Here is my style sheet:
const styles = StyleSheet.create({
simpleContainer: {
flex:1,
justifyContent: 'center',
},
container: {
flex: 1,
justifyContent: 'space-between',
backgroundColor: THEME_COLOR,
},
title: {
flex: 1,
marginTop: '15%',
marginLeft: '3%',
fontWeight: 'bold',
fontSize: TITLE,
color: DARK_THEME_CONTENT_COLOR_PRIMARY,
},
textContentDimmed: {
fontSize: TITLE_SECONDARY,
color: DARK_THEME_CONTENT_COLOR_SECONDARY,
},
textContentWhite: {
fontSize: TITLE_SECONDARY,
color: DARK_THEME_CONTENT_COLOR_PRIMARY,
},
textContentDark: {
fontSize: TITLE_SECONDARY,
color: LIGHT_THEME_CONTENT_COLOR_SECONDARY,
},
indentLeft: {
marginLeft:'10%',
},
forwardButtonLocation: {
flex: 1,
justifyContent: 'flex-start',
},
whiteLine: {
width: '100%',
height: 1,
marginTop: 4,
marginHorizontal: '6%',
backgroundColor: DARK_THEME_CONTENT_COLOR_PRIMARY,
},
});
Is there any way to automatically relocate the button when the size of the textInput changes?

Styles are different on IOS and Android in React Native

My render function is as follows :
render() {
return (
<View style={styles.container}>
<Camera
style={styles.camera}
ref={(cam) => {
this.camera = cam;
}}
onZoomChanged={this.onZoomChanged.bind(this)}
onFocusChanged={this.onFocusChanged.bind(this)}
torchMode={this.state.torch}
flashMode={this.state.flash}>
{this.imageOverlay()}
</Camera>
<View style={styles.commandBar}>
<TouchableHighlight onPress={this.fromLocal.bind(this)}>
<View style={styles.capture}>
<Icon .../>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={this.takePicture.bind(this)}>
<View style={styles.captureN}>
<Icon style={{transform: [{rotate: '90deg'}],}} .../>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={this.onTorchToggle.bind(this)}>
<View style={styles.capture}>
<Icon ... />
</View>
</TouchableHighlight>
</View>
</View>
);
}
I removed I few TouchableHighlight from the code above to make te code smaller.
And the styles are as follows:
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column'
},
camera: {
justifyContent: 'flex-end',
alignItems: 'center',
width: dw.width,
height: dw.height,
flexDirection:'column'
},
commandBar: {
flex: 0,
bottom: 85,
flexDirection: 'row',
alignItems: 'center',
justifyContent: "center"
},
capture: {
backgroundColor: '#444',
opacity: 0.7,
borderRadius: 5,
padding: 8,
paddingTop: 5,
paddingBottom: 5,
width: 55,
marginLeft: 8,
alignItems: 'center',
transform: [{rotate: '90deg'}],
},
firstCapture: {
marginLeft: 0
},
captureN: {
backgroundColor: '#444',
opacity: 0.7,
borderRadius: 5,
padding: 10,
width: 60,
marginLeft: 8,
alignItems: 'center'
},
imageContainer: {
flexDirection: 'row',
alignItems: 'flex-end'
},
innerImage: {
flex: 0,
height: dw.width,
width: dw.height,
marginBottom: 170,
resizeMode: 'contain',
transform: [{rotate: '90deg'}]
}
});
I want to take the photo with an image overlay in the landscape mode. On IOS it works fine, it looks as :
But on Android it doesn't work, I'm getting the screen as follows:
Any idea how to solve it?
Maybe you could try using different styles for Android and iOS with Platform. For example:
import { Platform, StyleSheet } from 'react-native';
const styles = StyleSheet.create({ height: (Platform.OS === 'ios') ? 200 : 100, });
Source: React Native Platform

In React Native, how do I put a view on top of another view, with part of it lying outside the bounds of the view behind?

I'm trying to make a layout as per below with React Native.
How do I specify the position of B relative to A?
With iOS Interface Builder and autoconstraints, this can very explicitly be done and is a breeze. It's not so obvious how one might achieve this with React Native.
Add the following style to the "floating" view:
position: 'absolute'
You may also need to add a top and left value for positioning.
The above solutions were not working for me. I solved it by creating a View with the same background colour as the parent and added negative margin to move the image upwards.
<ScrollView style={{ backgroundColor: 'blue' }}>
<View
style={{
width: '95%',
paddingLeft: '5%',
marginTop: 80,
height: 800,
}}>
<View style={{ backgroundColor: 'white' }}>
<Thumbnail square large source={{uri: uri}} style={{ marginTop: -30 }}/>
<Text>Some Text</Text>
</View>
</View>
</ScrollView>
and I got the following result.
You can use zIndex for placing a view on top of another. It works like the CSS z-index property - components with a larger zIndex will render on top.
You can refer: Layout Props
Snippet:
<ScrollView>
<StatusBar backgroundColor="black" barStyle="light-content" />
<Image style={styles.headerImage} source={{ uri: "http://www.artwallpaperhi.com/thumbnails/detail/20140814/cityscapes%20buildings%20hong%20kong_www.artwallpaperhi.com_18.jpg" }}>
<View style={styles.back}>
<TouchableOpacity>
<Icons name="arrow-back" size={25} color="#ffffff" />
</TouchableOpacity>
</View>
<Image style={styles.subHeaderImage} borderRadius={55} source={{ uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Albert_Einstein_1947.jpg/220px-Albert_Einstein_1947.jpg" }} />
</Image>
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "white"
},
headerImage: {
height: height(150),
width: deviceWidth
},
subHeaderImage: {
height: 110,
width: 110,
marginTop: height(35),
marginLeft: width(25),
borderColor: "white",
borderWidth: 2,
zIndex: 5
},
You can use this OverlayContainer. The trick is to use absolute with 100% size. Check below an example:
// #flow
import React from 'react'
import { View, StyleSheet } from 'react-native'
type Props = {
behind: React.Component,
front: React.Component,
under: React.Component
}
// Show something on top of other
export default class OverlayContainer extends React.Component<Props> {
render() {
const { behind, front, under } = this.props
return (
<View style={styles.container}>
<View style={styles.center}>
<View style={styles.behind}>
{behind}
</View>
{front}
</View>
{under}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
height: '100%',
justifyContent: 'center',
},
center: {
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
},
behind: {
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
left: 0,
top: 0,
width: '100%',
height: '100%'
}
})
import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native';
export default class App extends Component {
render() {
return (
<View>// you need to wrap the two Views an another View
<View style={styles.box1}></View>
<View style={styles.box2}></View>
</View>
);
}
}
const styles = StyleSheet.create({
box1:{
height:100,
width:100,
backgroundColor:'red'
},
box2:{
height:100,
width:100,
backgroundColor:'green',
position: 'absolute',
top:10,
left:30
},
});
You can use react-native-view-overflow plugin for placing a view on top of another. It works like the CSS z-index property.
import ViewOverflow from 'react-native-view-overflow';
<ViewOverflow />
<View style={[styles2.cardBox, { marginTop: 50 }]}>
<View style={[styles2.cardItem]} >
<Text style={styles2.cardHeader}>userList</Text>
</View>
<View style={[styles2.cardContent]}>
<Text style={styles2.text}>overflow: "visible"</Text>
</View>
<View style={[styles2.cardItemFooter]} >
<Text style={styles2.cardTextFooter}>...</Text>
</View>
</View>
</ViewOverflow>
const styles2 = StyleSheet.create({
cardBox: {
borderLeftWidth: 0,
borderTopWidth: 0,
backgroundColor: "transparent",
borderWidth: 1,
borderColor: "#d0d0d0",
width: '94%',
alignSelf: 'center',
height: 200,
position: "relative",
borderRadius: 15,
overflow: "visible" // doesn't do anything
},
cardContent: {
textAlign: "right",
backgroundColor: "transparent",
marginTop: 15,
alignSelf: 'flex-end',
padding: 5,
},
cardHeader: {
color: '#fff',
fontFamily: 'Vazir',
fontSize: 12
},
cardItem: {
backgroundColor: "#3c4252",
borderRadius: 3,
position: "absolute",
top: -10,
right: -5,
width: 50,
height: 20,
paddingRight: 5,
},
})
The easiest way to achieve this is with a negative margin.
const deviceWidth = RN.Dimensions.get('window').width
a: {
alignItems: 'center',
backgroundColor: 'blue',
width: deviceWidth,
},
b: {
marginTop: -16,
marginStart: 20,
},
You can use elevation property for Android if you don't mind the shadow.
{
elevation:1
}
Try this:
style = {{position: 'absolute', bottom: 20, left: 20, elevation: 100}}
Based on the example above i've created a component which stacks all childeren on top of each other. You could even nest OverlayContainers inside OverlayContainers.
Usage:
<OverlayContainer>
<View style={{backgroundColor:'red', width:150, height: 150}}></View>
<View style={{backgroundColor:'yellow', width:50, height: 50}}></View>
<Text>Just some text</Text>
</OverlayContainer>
Output:
import React, { FC, PropsWithChildren } from 'react'
import { StyleSheet, View } from 'react-native'
export const OverlayContainer: FC<PropsWithChildren<unknown>> = (props) => {
return (
<View style={styles.container}>
{props.children.map((child, index) => (
<View style={styles.child} key={index}>
{child}
</View>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
height: '100%',
},
child: {
position: 'absolute',
left: 0,
top: 0,
width: '100%',
height: '100%'
}
})
<SafeAreaView style={{ flex: 1 }} >
<View style={{ height: Dimensions.get('window').height / 2, backgroundColor: 'blue', justifyContent: 'center' }}>
<Text style={{ fontSize: 25, alignSelf: 'center' }} >A</Text>
<View style={{ justifyContent: 'center', height: 100, width: 100, backgroundColor: 'yellow', position: 'absolute', left: 20, top: Dimensions.get('window').height / 2 - 70 }}>
<Text style={{ fontSize: 22, alignSelf: 'center' }} >B</Text>
</View>
</View>
</SafeAreaView>