I've the following layout, and it need scroll when data is greater of screen:
Image:
Code:
export default () => (
<Container hasNavBar={false}>
<View style={{flex: 1}}>
<View style={Styles.container}>
<View style={{
flex: 1, backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text>Area 1</Text>
</View>
<View style={{
flex: 2, backgroundColor: 'yellow',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text>Area 2</Text>
</View>
</View>
</View>
</Container>
);
Following the documentation of react-native for add scroll I need create a wraper of my layout using ScrollView component, but when added scrollView component my layout broke:
Image:
Code:
export default () => (
<Container hasNavBar={false}>
<ScrollView style={{flex: 1}}>
<View style={Styles.container}>
<View style={{
flex: 1, backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text>Area 1</Text>
</View>
<View style={{
flex: 2, backgroundColor: 'yellow',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text>Area 2</Text>
</View>
</View>
</ScrollView>
</Container>
);
Container Component
<View style={flex: 1}>
{this.props.children}
<DropdownAlert
closeInterval={10000}
updateStatusBar={false}
ref={(ref) => this.dropdown = ref}
onClose={() => null}/>
</View>
How i solve it ?
After re-reading the question with better understanding of your complete code it became obvious that the quickest fix would be to define minHeight on Area 1 and Area 2's views. We can calculate it from window's Dimensions. This allows you to obtain the 33%/66% ratio with minimal content and expand either Area as needed with additional content.
Place this at the top of render():
const { height } = Dimensions.get('window');
Add to Area 1's style
minHeight: height / 3
And to Area 2's style
minHeight: (height / 3) * 2
Related
I am quite new to react native. I have created a FlatList for rendering this list of items, however, it is not scrolling. I've googled it for hours and tried nearly everything suggested in stack overflow threads - removed flex, added flex, wrapped it in a view, but nothing seems to work.
Here is my code (the issue is in the second FlatList) -
return(
<View style = {{ height: '100%' }}>
<View style = {{ width: '100%' }}>
<AppHeader />
</View>
<View style = {{ width: '100%'}}>
<View style = {{ width: '70%', alignSelf: 'center', flex: 1 }}>
<View>
<FlatList
data = {this.getTodayDay()}
renderItem = {this.renderItemDays}
keyExtractor = {this.keyExtractor}
/>
</View>
<FlatList
data = {this.getVisibleHours()}
renderItem = {this.renderItem}
keyExtractor = {this.keyExtractor}
scrollEnabled = {true}
/>
</View>
</View>
</View>
this.renderItem -
renderItem = () => {
// irrelevant code
if( isClass === true ){
return(
<ListItem bottomDivider = {true} style = {styles.renderItemActiveClass}>
<ListItem.Content>
<TouchableOpacity
onPress = {()=>{
this.props.navigation.navigate('ClassDetailsScreen', { "data": classData })
}}>
<ListItem.Title>{ definiteClassTime }</ListItem.Title>
<ListItem.Subtitle>{ classData.class_name }</ListItem.Subtitle>
</TouchableOpacity>
</ListItem.Content>
</ListItem>
)
}
else{
return(
<ListItem bottomDivider = {true} style = {styles.renderItemClass}
containerStyle = {styles.renderItemContent}>
<ListItem.Content>
<ListItem.Title>{item}:00</ListItem.Title>
<ListItem.Subtitle>No Class</ListItem.Subtitle>
</ListItem.Content>
</ListItem>
)
}
}
the StyleSheet -
renderItemClass: {
borderColor: 'purple',
borderWidth: 2
},
renderItemActiveClass: {
borderColor: 'green',
borderWidth: 2
},
renderItemContent: {
},
Could somebody please tell me what I'm doing wrong?
Add a height to both the flatlist. And also wrap your second flatlist within a seperate view. Here is an example:
return (
<View style={{ height: "100%" }}>
<View style={{ width: "100%" }}>
<AppHeader />
</View>
<View style={{ width: "100%" }}>
<View style={{ width: "70%", alignSelf: "center", flex: 1 }}>
<View style={{ height: 60, alignSelf: "center" }}>
<FlatList
data={this.getTodayDay()}
renderItem={this.renderItemDays}
keyExtractor={this.keyExtractor}
/>
</View>
<View style={{ height: 60, alignSelf: "center" }}>
<FlatList
data={this.getVisibleHours()}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
scrollEnabled={true}
/>
</View>
</View>
</View>
</View>
);
Ok, Let's make this simple. I've two Text components, one inside another. The first Text has fontSize of 60, and the nested one has fontSize of 20. As the font size varies, the nested Text sits base aligned. I want the nested Text vertically center aligned with the parent one.
Code
// #flow
import React, { Component } from 'react';
import { Text } from 'react-native';
type PropTypes = {}
export default class SampleVC extends Component<PropTypes> {
render() {
return (
<Text style={{ fontSize: 60 }}>
Big Text
<Text style={{ fontSize: 20 }}>Small Text</Text>
</Text>
);
}
}
Current Output
Needed Output
I know this is a simple scenario, but as am new to react native , i can't figure it out. I've searched all over the web,but couldn't find any helpful resource.
It's not possible to achieve what you're trying using just nested Text.
The Only option, use a View to wrap your texts like,
<View style={{ flexDirection: 'row', alignItems: 'center' }} >
<Text style={{ fontSize: 60 }}>Big Text</Text>
<Text style={{ fontSize: 20 }}>Small Text</Text>
</View>
And if you want to use it often, create your own custom component for the above like,
function CustomNextedText (props) {
return (
<View style={{ flexDirection: 'row', alignItems: 'center' }} >
<Text style={{ fontSize: 60 }}>{props.bigText}</Text>
<Text style={{ fontSize: 20 }}>{props.smallText}</Text>
</View>
);
}
Use it anywhere like any other react-native component,
<CustomNextedText bigText='Big Text' smallText='Small Text'/>
Hope it helps.
You can wrap nested Text in a View but nested View must have width and height. If you do not have any problem with this constraint, this is a good solution.
<Text style={{ fontSize: 60 }}>
Big Text
<View style={{ height:40, width:100, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontSize: 20 }}>Small Text</Text>
</View>
</Text>
you can also define the smallText lineHeight to match the bigText:
render() {
return (
<Text style={{ fontSize: 60 }}>
Big Text
<Text style={{ fontSize: 20, lineHeight:60 }}>
Small Text
</Text>
</Text>
);
}
Since React-Native v0.63 you can render <View/> inside <Text/>, without providing explicit dimensions for the View. Release Notes
With the accepted answer, if your Big Text is long enough to span multiple lines, the small text will be vertically centered to the entire block of Big Text, rather than a specific line.
So here's an update to #Ali S's answer using the new functionality. Height is still required in order to vertically center the nested text, so it is set to the fontSize of the Big Text. Width can be omitted, so the length of the small text can now be dynamic.
function BigSmallText(props) {
let bigFontSize = 40;
return (
<Text
style={{
fontSize: bigFontSize,
lineHeight: bigFontSize,
}}>
A very long sentence that spans multiple lines
<View
style={{
flexDirection: 'row',
alignItems: 'center',
height: bigFontSize,
}}>
<Text
style={{
fontSize: 14,
paddingLeft: 10,
}}>
SMALL TEXT
</Text>
<Text
style={{
fontSize: 6,
paddingLeft: 10,
}}>
TINY TEXT
</Text>
</View>
</Text>
);
}
You can add both Text into View.
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Text style={{ fontSize: 60, height:'100%' }}>Big Text</Text>
<Text style={{ fontSize: 20, height:'100%' }}>Small Text</Text>
</View>
< View style={{flexDirection:'column'}}>
<View style={{alignContent:'center'}}>
<Text style={{fontSize:60}}>{props.bigText}</Text>
</View>
<View style={{alignContent:'center'}} >
<Text style={{fontSize:20}}>{props.smallText}</Text>
</View>
< /View>
That seems odd, but here is something that seems to do the job for me (using #Ali SabziNezhad's suggestion). It allows to share text props (like color) and alignement (center in this particular case)
function Component() {
return (
<CenterText style={{color: 'red'}}>
Centered <Text style={{fontSize: 50}}>text</Text>
</CenterText>
);
}
export function CenterText({children, ...otherProps}: Text['props']) {
return (
<Text {...otherProps}>
<View
style={{flexDirection: 'row', alignItems: 'center'}}
children={children}
/>
</Text>
);
}
We could event have a more generic alignment text component:
export function AlignedText({children, alignItems, ...otherProps}: AlignedTextProps) {
return (
<Text {...otherProps}>
<View
style={{flexDirection: 'row', alignItems: alignItems}}
children={children}
/>
</Text>
);
}
type Alignment = 'baseline' | 'center' | 'flex-end' | 'flex-start' | 'stretch';
type AlignedTextProps = Text['props'] & {alignItems: Alignment};
Which we can then use to define CenterText:
export function CenterText(props: TextProps) {
return <AlignedText alignItems='center' {...props} />;
}
Or directly as:
function Component() {
return (
<AlignedText style={{color: 'red'}} alignItems='center'>
Centered <Text style={{fontSize: 50}}>text</Text>
</AlignedText>
);
}
I have a view having text inside it. The component looks like this:
MyComponent = () => {
return (
<View style={styles.viewStyle}>
<Text style={styles.textStyle}>My Text</Text>
</View>
);
}
const styles = {
viewStyle: {
backgroundColor: '#006699',
height: 40,
justifyContent: 'center',
alignItems: 'center',
},
textStyle: {
color: '#000000',
fontSize: 16,
}
}
When this component gets used, I want my View to have a custom width such that it just wraps my text. Here's the visual clue:
It's about the original design of Layout with Flexbox.
You can make it work by either add flexDirection: 'row' to it's parent view (so it will stretch automatically related to <Text /> width),
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={styles.viewStyle}>
<Text style={styles.textStyle}>My Text</Text>
</View>
</View>
or give width to it directly.
<View style=[{styles.viewStyle}, {width: 50}]>
<Text style={styles.textStyle}>My Text</Text>
</View>
Result of option 1:
I am creating list of items on react native app. I want to make swipe to left and right every item of this list. So when I swipe to left I want to hide Views that was rendered and show new elements. Also when I swipe to right I want to display other elements that will be different from that element that will be rendered when I swipe left. I found this library called "react-native-swipe-gestures" but I can't figure out how to display and hide elements with it. I declared some items but when I try to display it i got an error that "can't find variable 'item'" maybe you will have some explain to me how I should use it to actually get working swipe left and right.
import React, {Component} from 'react';
import {
ScrollView,
Text,
View,
Image,
Button
} from 'react-native';
import GestureRecognizer, {swipeDirections} from 'react-native-swipe-gestures';
import {List, ListItem} from "react-native-elements";
class Offers extends Component {
constructor(props) {
super(props);
this.state = {
myText: '',
gestureName: 'none',
icons: '',
guardian: '',
area: '',
rooms: '',
floor: '',
market: '',
year: '',
pricePerMeter: '',
};
}
onSwipeRight(gestureState) {
this.setState({myText: 'You swiped right!'});
}
onSwipe(gestureName, gestureState) {
const {SWIPE_LEFT, SWIPE_RIGHT} = swipeDirections;
this.setState({gestureName: gestureName});
switch (gestureName) {
case SWIPE_LEFT:
this.setState({backgroundColor: 'blue'});
break;
case SWIPE_RIGHT:
this.setState({backgroundColor: 'yellow'});
break;
}
}
onSwipeLeft(gestureState) {
this.setState({
guardian: item.offerGuardian, //items from const offers
area: item.offerArea,
floor: item.offerFloor,
rooms: item.offerRooms,
market: item.offerMarket,
year: item.offerYear,
pricePerMeter: item.offerPricePerMeter,
})
}
render() {
const config = {
velocityThreshold: 0.3,
directionalOffsetThreshold: 80
};
const offers = [
{
offerNumber: 'TEST912697',
offerLocation: 'Warszawa Białołęka',
offerStreet: 'ul. Bruszewska',
offerType: 'Mieszkanie',
offerStatus: 'Akt. Wewnętrzna',
offerStatusColor: '#0FBEB2',
offerAddDate: '2017-09-20 12:08:06',
offerPrice: '2 450 000',
photo: 'https://static.pexels.com/photos/164516/pexels-photo-164516.jpeg',
offerGuardian: 'Adam Borek',
offerTransactionType: 'sprzedaż',
offerArea: '50 m2',
offerRooms: '2 pokoje',
offerFloor: '1 z 2',
offerYear: '2005 rok',
offerMarket: 'rynek pierwotny',
offerPricePerMeter: '5000 zł/m2'
},
];
return (
<ScrollView>
<View style={{
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'flex-end'
}}>
<View style={{marginRight: 20, marginTop: 10}}>
<Button title="akcje"/>
</View>
</View>
{offers.map((item, i) => (
<View key={i}>
<List>
<GestureRecognizer
onSwipe={(direction, state) => this.onSwipe(direction, state)}
onSwipeLeft={(state) => this.onSwipeLeft(state)}
onSwipeRight={(state) => this.onSwipeRight(state)}
config={config}
style={{
flex: 1,
backgroundColor: this.state.backgroundColor
}}
>
<ListItem
roundAvatar
subtitle={
<View style={{flexDirection: 'row'}}>
<View>
<Text>{this.state.myText}</Text>
<Text>{this.state.guardian}</Text>
<Text>{this.state.area}</Text>
<Text>{this.state.floor}</Text>
<Text>{this.state.market}</Text>
<Text>{this.state.year}</Text>
<Text>{this.state.pricePerMeter}</Text>
<Image source={require('../../gfx/lel.jpg')}
style={{
height: 100,
width: 150
}}/>
</View>
<View style={{
marginLeft: 5,
flexDirection: 'row',
flexWrap: 'wrap'
}}>
<View style={{width: 140}}>
<Text>
{item.offerLocation}
{"\n"}
{item.offerStreet}
{"\n"}
{item.offerType} na {item.offerTransactionType}
{"\n"}
{item.offerNumber}
</Text>
</View>
<View>
<View style={{
justifyContent: 'flex-end',
width: 95,
height: 30,
backgroundColor: item.offerStatusColor
}}>
<Text style={{color: '#fff', textAlign: 'center'}}>
{item.offerStatus}
</Text>
</View>
<View style={{
flexDirection: 'column',
alignItems: 'flex-end',
flexWrap: 'wrap'
}}>
<Text style={{fontSize: 20}}>
{"\n"}
{"\n"}
{item.offerPrice}
</Text>
</View>
</View>
</View>
</View>
}
onPress={() => this.props.navigation.navigate('OffersDetails')}
/>
</GestureRecognizer>
</List>
</View>
))}
</ScrollView>
)
}
}
export default Offers;
I would recommend trying out this libray react-native-swipe-list-view. It is well documented and easy to use for any type of swipable row. https://github.com/jemise111/react-native-swipe-list-view
The basic concept is that you have one element in front of a hidden element. When you swipe it just reveals the hidden element below.
I am using FlatList to view list of people, however, I have noticed that the last item is always a little off:
See item Amy Butts, I have to drag to top in order to see it. This screen is within a stackNavigator that has a header. Would that be the issue? how to solve it?
I tried marginBottom: 40 on the FlatList but it did not change anything.
Code:
let renderRow = ({item}) => {
return (
<View style={{flexDirection: "row", justifyContent: "space-between"}}>
<TouchableOpacity style={{ flexDirection: "row", justifyContent: "flex-start", marginLeft: 10}} onPress={this.myFunction.bind(this, item)} >
<View style={{}}>
<Image style={styles.Image} source={{uri: item.Image}} />
</View>
<View style={{ marginTop: 15, marginLeft: 10}}>
<Text >{item.name}</Text>
</View>
</TouchableOpacity>
</View>
);
}
return(
<FlatList style={{marginTop: 10, backgroundColor: "white"}}
keyExtractor={(item, index) => item.id}
data={this.state.result}
renderItem={renderRow.bind(this)}
ItemSeparatorComponent={renderSeparator.bind(this)}
/>
)
With paddingBottom (or top), now the last two items will not be shown:
You need to add paddingBottom or marginBottom to the FlatList with a suitable value to your design.
// Some padding amount that is suitable for your design
<FlatList style={{marginTop: 10, backgroundColor: "white", paddingBottom: 40}}
keyExtractor={(item, index) => item.id}
data={this.state.result}
renderItem={renderRow.bind(this)}
ItemSeparatorComponent={renderSeparator.bind(this)}
/>