I have a grid with a row and a col in that row. I copied the row with its col and pasted it under the first row so I could test having 2 cols under each other. That part works but sadly, they are sticking on eachother. There's no space/padding between them. I tried adding a top: 20 to the row and col but neither of that is working, in fact it makes the height of the second col even shorter.
Any ideas on how I can fix this? This is React Native with Native Base.
<Content>
<Grid style={Style.contentContainer}>
<Row style={Style.content}>
<Col>
<Text>Test</Text>
<View style={Style.completelyCenteredComponent}>
<Text>Text here</Text>
</View>
</Col>
</Row>
<Row style={Style.content}>
<Col>
<Text>Test</Text>
<View style={Style.completelyCenteredComponent}>
<Text>Text here</Text>
</View>
</Col>
</Row>
</Grid>
</Content>
Style:
module.exports = StyleSheet.create({
mainApp: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%'
},
backgroundImage: {
flex: 1,
resizeMode: 'cover'
},
contentContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
content: {
backgroundColor: 'rgba(255, 255, 255, 0.84)',
minWidth: '88%',
maxWidth: '88%',
height: 200,
top: 0,
padding: 26,
borderWidth: 0.6,
borderColor: '#000000'
},
completelyCenteredComponent: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
});
You need add marginBottom for your content and create other style for last row with marginBottom: 0.
Your style:
content: {
... your style
marginBottom: 20,
},
lastRow: {
marginBottom: 0,
}
And your component:
<Grid>
<Row style={style.content}>...</Row>
<Row style={[style.content, style.lastRow]}>...</Row>
</Grid>
in my point of view try adding margin at content object of styling
it would work i think. and where did you add the top:20 there is no such code in there in styling
Related
I am using the React Native PanResponder class to allow for drag and drop if elements of the screen.
What I have discovered is that the onLayout is not returning the x absolute positions, it's being affected by its parent views and is returning weird results.
For example the current view has 3 columns and the onLayout resides in the middle column. It is returning it's x value as 146.5. Which is not the absolute position.
How would I get the absolute position of the element if it resides in multiple parent views?
// Omitted some code for clarity
const dropZoneValues = React.useRef(null);
const pan = React.useRef(new Animated.ValueXY());
const setDropZoneValues = React.useCallback((event) =>
{
dropZoneValues.current = event.nativeEvent.layout;
}, []);
return (
<Main background={bg} showHeader={false}>
<Row rowStyles={{
textAlign: 'center', marginLeft: 50, marginRight: 50,
alignSelf: 'center',
alignItems: 'center',
textAlignVertical: 'center',
justifyContent: 'center',
}}>
<Col xs={4} sm={4} md={4} lg={4}>
</Col>
<Col xs={4} sm={4} md={4} lg={4}>
<View
onLayout={setDropZoneValues}
style={styles.dropZone}>
<Text style={styles.text}>Drop me here!</Text>
</View>
{renderDraggable()}
</Col>
<Col xs={4} sm={4} md={4} lg={4}>
</Col>
</Row>
</Main>
);
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
padding: 20,
flexDirection: 'column',
},
dropZone: {
height: 100,
backgroundColor: '#2c3e50',
width: 100,
alignSelf: 'center',
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
},
text: {
marginTop: 25,
marginLeft: 5,
marginRight: 5,
textAlign: 'center',
color: '#fff'
},
draggableContainer: {
zIndex: 99999
},
circle: {
backgroundColor: '#1abc9c',
width: 80,
height: 80,
borderRadius: CIRCLE_RADIUS,
zIndex: 99999,
position: 'absolute'
}
});
onLayout returns positions relative to parents. You can instead use event.target.measure within the onLayout callback to find the absolute position (though note this is marginally worse for performance).
<MyComponent
onLayout={(event) => {
event.target.measure(
(x, y, width, height, pageX, pageY) => {
doSomethingWithAbsolutePosition({
x: pageX,
y: pageY,
});
},
);
}}
/>
(hat tip to https://stackoverflow.com/a/64882955/842506)
Alright, so this has got me busy for quite a few hours already. I am trying to create a login screen where the main components are rendered on the bottom, with the logo in the remaining space. This is kind of what I would like to achieve:
To support my textinputs, I use KeyboardAwareScrollView, as it works better for me as opposed to KeyboardAvoidingView. My code currently looks like this (I plan on using a background image with a 50% color overlay rather than the red background, so the ImageBackground has to stay in place too):
<ImageBackground
source={require('./assets/img/background-clouds.png')}
resizeMode="cover"
style={styles.backgroundImage}>
<View style={styles.backgroundOverlay} />
<View style={styles.dummyView}>
<Text>elloha</Text>
</View>
<Image
source={require('./assets/img/logo.png')}
style={styles.backgroundLogo}
resizeMode="contain"
/>
<KeyboardAwareScrollView
keyboardShouldPersistTaps="always"
keyboardOpeningTime={0}
alwaysBounceHorizontal={false}
alwaysBounceVertical={false}
contentInsetAdjustmentBehavior="automatic"
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
automaticallyAdjustContentInsets={false}
extraScrollHeight={30}
enableOnAndroid>
<StatusBar
backgroundColor="transparent"
barStyle="light-content"
hidden={false}
translucent
/>
<TouchableWithoutFeedback
onPress={Keyboard.dismiss}
accessible={false}>
<View style={styles.content}>
<View style={styles.backgroundContainer}>
<SafeAreaView style={{ flex: 0 }} />
<View style={styles.loginContainer}>
<View style={styles.loginScreen}>
// textinputs and buttons go here
</View>
<SafeAreaView style={{ backgroundColor: 'white' }} />
</View>
<View
style={{
backgroundColor: 'white',
height: Dimensions.get('window').height,
position: 'absolute',
width: Dimensions.get('window').width,
top: Dimensions.get('window').height,
}}
/>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAwareScrollView>
</ImageBackground>
Relevant styles:
const styles = StyleSheet.create({
container: {
backgroundColor: "white",
},
content: {
flex: 1,
},
backgroundImage: {
flex: 1,
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0,
width: Dimensions.get("window").width,
height: Dimensions.get("window").height,
},
backgroundContainer: {
justifyContent: "flex-end",
flex: 1,
width: Dimensions.get("window").width,
height: Dimensions.get("window").height,
},
backgroundOverlay: {
backgroundColor: "red",
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
},
logoContainer: {
top: "10%",
width: "100%",
},
backgroundLogo: {
alignSelf: "center",
position: "absolute",
width: 126,
height: 96,
},
dummyView: {
backgroundColor: "red",
flex: 1,
},
loginContainer: {
borderTopEndRadius: 30,
borderTopStartRadius: 30,
width: "100%",
backgroundColor: "white",
height: 500,
alignItems: "center",
paddingTop: Dimensions.get("window").width * 0.1,
},
loginScreen: {
width: "80%",
backgroundColor: "white",
},
});
This yields the following result:
I can get it done by adding top: 160 to the backgroundLogo style, but that's a fixed value. I want it to be always in the center of the available space, but I'm unable to add a view between the background and the loginContainer, as all the logic for the keyboard and such is handled in between.
Is there a way to achieve what I want? Ideally, I should also be able to check the available height, and only show the logo if there is enough space (e.g. available height > 100, otherwise don't show logo).
Important:
I want the logo to stay fixed, so if the keyboard is shown, the logo should not move up. The loginContainer should go "over" the logo
EDIT:
Wrap Image inside a View with this style and give the loginContainer style height: '70%' :
...
<View style={styles.dummyView}>
<Text>elloha</Text>
</View>
<View
style={{
justifyContent: 'center',
alignItems: 'center',
height: '30%',
position: 'absolute',
width: '100%',
}}>
<Image
source={require('./assets/img/logo.png')}
style={styles.backgroundLogo}
resizeMode="contain"
/>
</View>
<KeyboardAwareScrollView
keyboardShouldPersistTaps="always"
...
...
loginContainer: {
borderTopEndRadius: 30,
borderTopStartRadius: 30,
width: '100%',
backgroundColor: 'orange',
height: '70%',
alignItems: 'center',
paddingTop: Dimensions.get('window').width * 0.1,
},
...
hie! I think using Dimension to get a specific screen's height and deciding it has 70% of the screen covered via form sheet and rest is free for a logo to be in and we can ask it to be down a little using rest of height's 50% as margin-top ( the image will be in the center of that image )
here is a SNACK LINK to see your example working with my suggested solution.
here is the draft code:
import * as React from 'react';
import { Text, View, StyleSheet, Dimensions, ImageBackground,TextInput,
Image, TouchableWithoutFeedback, Keyboard, SafeAreaView, StatusBar} from 'react-native';
import Constants from 'expo-constants';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
export default function App() {
return (
<ImageBackground
source={{
uri: 'https://cdn.pixabay.com/photo/2021/08/23/18/37/tea-6568547_960_720.jpg',
}}
resizeMode="cover"
style={styles.backgroundImage}>
<View style={styles.backgroundOverlay} />
<Image
source={require('./assets/snack-icon.png')}
style={styles.backgroundLogo}
resizeMode="contain"
/>
<KeyboardAwareScrollView
keyboardShouldPersistTaps="always"
keyboardOpeningTime={0}
alwaysBounceHorizontal={false}
alwaysBounceVertical={false}
contentInsetAdjustmentBehavior="automatic"
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
automaticallyAdjustContentInsets={false}
extraScrollHeight={30}
enableOnAndroid>
<StatusBar
backgroundColor="transparent"
barStyle="light-content"
hidden={false}
translucent
/>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={styles.content}>
<View style={styles.backgroundContainer}>
<SafeAreaView style={{flex: 0}} />
<View style={styles.loginContainer}>
<View style={styles.loginScreen}>
<TextInput value={'email'} style={{borderBottomWidth:1, padding:10}}/>
<TextInput value={'password'} style={{borderBottomWidth:1, padding:10}}/>
</View>
<SafeAreaView style={{backgroundColor: 'white'}} />
</View>
<View
style={{
backgroundColor: 'white',
height: Dimensions.get('window').height,
position: 'absolute',
width: Dimensions.get('window').width,
top: Dimensions.get('window').height,
}}
/>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAwareScrollView>
</ImageBackground>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
},
content: {
flex: 1,
},
backgroundImage: {
flex: 1,
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
backgroundContainer: {
justifyContent: 'flex-end',
flex: 1,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
backgroundOverlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
logoContainer: {
top: '10%',
width: '100%',
},
backgroundLogo: {
alignSelf: 'center',
position: 'absolute',
marginTop: Dimensions.get('window').height/7, // top for rest of the screen to push logo down
width: 126,
height: 96,
},
dummyView: {
backgroundColor: 'red',
flex: 1,
},
loginContainer: {
borderTopEndRadius: 30,
borderTopStartRadius: 30,
width: '100%',
backgroundColor: 'white',
height: Dimensions.get('window').height/1.5, //container of form height
alignItems: 'center',
paddingTop: Dimensions.get('window').width * 0.1,
},
loginScreen: {
width: '80%',
backgroundColor: 'white',
},
});
Here is the output of code on android/ios:
I am using the react-native-mapbox-gl library and I am showing some points on a map. Each has its own callout to display additional information when the respective point is pressed.
I have found the docs/Callout.md and Callout.js source and and example using it in example/src/examples/ShowPointAnnotation.js. This was a great help, thank you so much for the example... I might though doing something really wrong and I have spent days already on this...
My issue is that when I press one annotation, the styling of the annotations appears to be lost (they go all black). Similarity, the styling for the callouts don't seem to be applied. They all black, too. I have shared code and screenshots bellow.
<MapboxGL.PointAnnotation
key={id}
id={id}
coordinate={coordinate}
title={title}
onSelected={feature => {
debugger
this.onAnnotationSelected(i, feature)
}}
onDeselected={this.onAnnotationDeselected}
>
<View
style={[
styles.annotationContainer,
{
backgroundColor: bgColour,
borderRadius: ANNOTATION_SIZE / 2,
borderWidth: StyleSheet.hairlineWidth,
borderColor: borderColor
}
]}
>
<Text style={[styles.annotationFill, { color: borderColor }]}>
{studio.id}
</Text>
</View>
<MapboxGL.Callout
style={[
styles.calloutContainer,
{ backgroundColor: bgColour, borderColor: borderColor }
]}
title={title}
>
<View
style={[
styles.calloutContent,
{
backgroundColor: bgColour,
borderColor: borderColor
}
]}
>
<Text style={[styles.annotationFill, { color: borderColor }]}>
{title}
</Text>
</View>
<View
style={[
styles.tip,
styles.calloutContent,
{
backgroundColor: bgColour,
borderColor: borderColor
}
]}
/>
</MapboxGL.Callout>
</MapboxGL.PointAnnotation>
And stylings
const ANNOTATION_SIZE = 32
const styles = StyleSheet.create({
annotationContainer: {
width: ANNOTATION_SIZE,
height: ANNOTATION_SIZE,
alignItems: 'center',
justifyContent: 'center'
},
annotationFill: {
color: 'black'
},
container: {
flex: 1
},
calloutContainer: {
alignItems: 'center',
justifyContent: 'center',
width: 180,
zIndex: 9999999
},
calloutContent: {
flex: 1,
position: 'relative',
padding: 8,
borderRadius: 3,
borderWidth: 1
},
calloutTitle: {
width: ANNOTATION_SIZE,
height: ANNOTATION_SIZE,
color: 'black',
textAlign: 'center'
},
calloutTip: {
zIndex: 1000,
marginTop: -2,
elevation: 0,
backgroundColor: 'transparent',
borderTopWidth: 16,
borderRightWidth: 8,
borderBottomWidth: 0,
borderLeftWidth: 8,
borderTopColor: 'white',
borderRightColor: 'transparent',
borderBottomColor: 'transparent',
borderLeftColor: 'transparent'
}
})
I am concerned though as well that I should not be using PointAnnotation, as it is marked to be deprecated. Is there an alternative way to achieve the same? Could someone point me into right direction? I am happy to contribute too if needed.
I am trying to put a button (custom component made from TouchableOpacity inside View) and an image in a view.....and have them sit side by side.
See code below
<View
style={{
borderColor: 'black',
borderWidth: 1,
flex: 1,
flexDirection: 'row',
}}
>
<MyButton
to_extraStyle={{
backgroundColor: '#03A9F4',
width: 100,
height: 60,
alignSelf: 'flex-start',
}}
onPress={this._imagePickHandler}
>
CHOOSE PIC
</MyButton>
<Image
source={{ uri: this.state.localImgUrl }}
style={{
width: 100,
height: 60,
borderColor: 'black',
borderWidth: 1,
alignSelf: 'flex-end',
}}
/>
</View>
When I remove flexDirection: 'row' you can see both the image and the button....they sit on top of each other....but with flexDirection: 'row' included, the image disappears and you can only see the button.
Any ideas?
Use the value of width as %.
<View
style={{
borderColor: 'black',
borderWidth: 1,
flex: 1,
flexDirection: 'row'
}}
>
<MyButton
to_extraStyle={{
backgroundColor: '#03A9F4',
width: "50%",
height: 60,
}}
onPress={this._imagePickHandler}
>
CHOOSE PIC
</MyButton>
<Image
source={{ uri: this.state.localImgUrl }}
style={{
width: "50%",
height: 60,
borderColor: 'black',
borderWidth: 1,
}}
/>
</View>
Example
export default class App extends Component {
render() {
return (
<View style={s.container}
>
<TouchableOpacity style={s.touchable}>
<Text style={{color:"#ffffff"}}>Button </Text>
</TouchableOpacity>
<Image source={{uri: 'http://i.imgur.com/IGlBYaC.jpg'}} style={s.backgroundImage} />
</View>
);
}
}
const s = StyleSheet.create({
backgroundImage: {
width: "50%",
height: 60,
borderColor: 'black',
borderWidth: 1,
},
touchable: {
backgroundColor: '#03A9F4',
width: "50%",
height: 60,
justifyContent:"center",
alignItems:"center"
},
container: {
borderColor: 'white',
borderWidth: 1,
flex: 1,
flexDirection: 'row'
}
});
Remove alignSelf on both MyButton and Image and they will sit side by side.
If what you wanted to obtain with alignSelf is to align MyButton at the very left and Image at the very right then add justifyContent: 'space-between' to your view.
I am attempting to align an image within and ImageBackground component though no matter what I do, it doesn't appear to follow the flexbox rules.
Below is the desired result
But I am currently getting
Below is the code I have used
render () {
console.log(this.props.data.attributes.main_image_url)
return (
<TouchableOpacity onPress={this._handlePress} style={styles.container}>
<ImageBackground source={{uri: "https:"+this.props.data.attributes.main_image_url}} style={styles.background}>
<View style={styles.logoContainer}>
<Image
// defaultSource={require('../Images/logo-placeholder.png')}
source={{uri: "https:"+this.props.data.attributes.logo_url}}
resizeMode="contain"
style={styles.logo}
/>
</View>
</ImageBackground>
</TouchableOpacity>
)
}
Styles
container: {
marginBottom: Metrics.doubleSection,
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'stretch',
},
background: {
height: Metrics.screenWidth / 2,
width: Metrics.screenWidth-(Metrics.baseMargin*2),
margin: Metrics.baseMargin
},
logoContainer: {
backgroundColor: Colors.coal,
justifyContent: 'flex-end',
alignItems: 'left',
left: Metrics.doubleBaseMargin,
height: Metrics.images.xl,
width: Metrics.images.xl
},
logo: {
height: Metrics.images.xl,
width: Metrics.images.xl
}
Change your logoContainer style as below set position:'absolute' and set bottom:negative value:
logoContainer: {
backgroundColor: Colors.coal,
justifyContent: 'flex-end',
alignItems: 'flex-start',
position:'absolute', // set position to absolute
bottom:-10, //give relative value here
left: Metrics.doubleBaseMargin,
height: Metrics.images.xl,
width: Metrics.images.xl
},