How to have elements automatically relocate themselves when one element changes its size in react native? - 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?

Related

React native Modal box content overflow

I am having the following modal box. Problem is whatever renderContent displays gets overflows visually outside the right boundary of modal box. How to fix it?
<Modal
transparent
animationType="fade"
visible={this.state.visible}
onRequestClose={this.hideModal}
>
<Container style={styles.overlay}>
<View style={[styles.container]}>
{ this.renderContent() }
</View>
</Container>
</Modal>
renderContent = () => {
return (
<ShopList
ref={ref => (this.shopList = ref)}
loadData={this.props.fetch}
/>
);
};
styles
overlay: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: Colors.overlay,
},
container: {
backgroundColor: Colors.white,
borderRadius: Metrics.WIDTH * 0.04,
flexDirection: 'column',
width: '96%',
},
Did you try this?
container: {
overflow: hidden,
backgroundColor: Colors.white,
borderRadius: Metrics.WIDTH * 0.04,
flexDirection: 'column',
width: '96%',
},
If not work, define max and min lengths to width content

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',
},

Adding margin to component changes screen layout react-native

I'm building a react-native app and I'm having a problem styling the components.
For some reason when I add a margin to one of the components the main component doesn't occupy the full height of the screen even though is "flex:1".
In this example the problem happens with the back button, if I use padding it works fine but I need to use margin so the user doesn't press the wrong component by mistake.
And the same problem happens in the rest of the app with different components that have a margin property.
Main component
body: {
flex: 1,
backgroundColor: 'green'
},
subHeader: {
backgroundColor: '#f4f4f4',
height: 95,
flexDirection: 'row'
},
vericalBar: {
width: 9
},
subHeaderDescription: {
flex: 1,
justifyContent: 'center',
marginLeft: 16
},
subHeaderLocation: {
color: '#2d2d2d',
fontSize: 14,
marginBottom: 10
},
subHeaderText: {
color: '#2d2d2d',
fontSize: 20
},
subHeaderStatus: {
alignItems: 'center',
justifyContent: 'center',
marginRight: 18
},
listDescription: {
backgroundColor: 'red',
flexGrow: 1,
paddingTop: 16,
paddingLeft: 20
},
taskDescription: {
color: '#2d2d2d',
fontSize: 16
}
<View style={localStyles.body}>
<Header navigation={this.props.navigation} />
<View style={localStyles.subHeader}>
<View style={[localStyles.vericalBar, { backgroundColor: task.color }]} />
<View style={localStyles.subHeaderDescription}>
<Text style={localStyles.subHeaderLocation}>{location.name}</Text>
<Text style={localStyles.subHeaderText}>{task.name}</Text>
</View>
{iconSelector(task)}
</View>
<BackButton navigation={this.props.navigation} />
<View style={localStyles.listDescription}>
<Text style={localStyles.taskDescription}>{task.description}</Text>
</View>
{returnStatus(task)}
<ReportIssueButton navigation={this.props.navigation} />
<Footer navigation={this.props.navigation} />
</View>
Back Button
<TouchableWithoutFeedback onPress={() => navigation.goBack()}>
<View style={localSytles.container}>
<Image style={{ width: 14, height: 14 }} source={require('../../Images/Back.png')} />
<Text style={localSytles.buttonText}>Back</Text>
</View>
</TouchableWithoutFeedback>
container: {
flexDirection: 'row',
height: 40,
paddingLeft: 20,
alignItems: 'center',
backgroundColor: 'blue'
},
buttonText: {
color: '#2d2d2d',
fontSize: 14,
marginLeft: 10
}
I've found the problem, the container "listDescription" had a "paddingTop: 16"
by removing that property it allowed the container to push the rest of the containers down.

react native 2 colors as background

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

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