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>
);
Related
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>
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 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'
}
});
This seems like an easy question at first but it's actually tricky.
Better to go directly to the example. I've created a snack with the sample code here https://snack.expo.io/BkSNtNrWV
I want to have a list of items with given aspect ratio (say 3:2) and the items should take as much space as possible with a maximum limit on size. This sample code does it:
<View>
<FlatList style={{backgroundColor:'lightgray'}}
data={[{key: 'a'},{key: 'b'}]}
renderItem={({item}) =>
<View style ={styles.pink}></View>
}/>
</View>
const styles = StyleSheet.create({
pink: {
backgroundColor: "#A37E93",
maxHeight: 150,
aspectRatio: 3/2,
borderWidth: 1,
}});
And this is the result:
However, the problem is that I would like to have the items aligned to the center. I tried to wrap the list item in a flexbox with 'row' direction but that caused the item to have 0 height => not displayed. Justify content didn't help either (it's possible that I do it incorrectly).
Does anyone know how to solve this please?
Updated the code. Add flex to inner item and wrap the view inside another with screen width.
import * as React from 'react';
import { Text, View, StyleSheet,FlatList,Dimensions } from 'react-native';
import { Constants } from 'expo';
const{width} = Dimensions.get('window')
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default class App extends React.Component {
render() {
return (
<View>
<FlatList style={{backgroundColor:'lightgray'}}
data={[{key: 'a'},{key: 'b'}]}
renderItem={({item}) =>
<View style={styles.item}>
<View style ={styles.pink}></View>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
item:{
width:width,
height:150,
alignItems:'center'
},
pink: {
flex:1,
backgroundColor: "#A37E93",
maxHeight:150,
aspectRatio:3/2,
borderWidth:1,
}
});
I'm trying to use percentage value for margin style attribute on my React Native project but it seems to reduce the height of one of my View component. If I replace percentage value by an absolute value, there is no more issue and it works fine. Did you try to use percentage value as margin in React Native ? Here is a little sample of code to reproduce this issue:
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.scene}>
<View style={styles.card}>
<View style={styles.container}>
<Text>Hello World</Text>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
scene: {
backgroundColor: '#F9E8D5',
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
flexDirection: 'column'
},
card: {
backgroundColor: '#E6D5C3',
flex: 0.2,
flexDirection: 'column',
marginTop: '20%' // Replace by 20
},
container: {
backgroundColor: '#FFFFFF',
flex: 1,
flexDirection: 'column',
justifyContent: 'center'
}
});
Thank you very much !
A component's height and width determine its size on the screen.
The simplest way to set the dimensions of a component is by adding a fixed width and height to style. All dimensions in React Native are unitless, and represent density-independent pixels.
Setting dimensions this way is common for components that should always render at exactly the same size, regardless of screen dimensions.
Use flex in a component's style to have the component expand and shrink dynamically based on available space. Normally you will use flex: 1.
The following references will be use for styling
https://facebook.github.io/react-native/docs/height-and-width.html
https://medium.com/the-react-native-log/tips-for-styling-your-react-native-apps-3f61608655eb
https://facebook.github.io/react-native/docs/layout-props.html#paddingtop
Use Dimensions to calculate to get the height and width of the screen.
var {height, width} = Dimensions.get('window');
To specify percentage by getting the screen size and convert it into percentage.
Sample example:
const { height } = Dimensions.get('window');
paddingTop: height * 0.1 // 10 percentage of the screen height
This is a real bug but Facebook does not care.
https://github.com/facebook/react-native/issues/19164