How to change height of <FlatList/> in react native? - react-native

I want to change width and height of <FlatList />.
I set the height style to the current <FlatList /> but it never worked.
I can change the height of <FlatList /> in no way.
This is my render() function and styles.
render() {
const listData = [];
listData.push({ key: 0 });
listData.push({ key: 1 });
listData.push({ key: 2 });
listData.push({ key: 3 });
listData.push({ key: 4 });
return (
<View style={styles.container}>
<FlatList
data={listData}
renderItem={({item}) => {
return (
<View
style={{
width: 30, height: 30, borderRadius: 15, backgroundColor: 'green'
}}
/>
)
}}
horizontal
style={styles.flatList}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
},
flatList: {
height: 50,
backgroundColor: 'red'
}
});
And this is result of this code.
I found the answers for several hours but nothing helped me.
I am not sure why height style is not working.
Any help is appreciated.

adding flexGrow: 0 to the flatList style worked for me, so it will be:
flatList: {
height: 50,
backgroundColor: 'red',
flexGrow: 0
}

Set the height of <View/> and place <FlatList/> inside that <View/>

Add flexGrow: 0. Don't mention height, the design might break when it comes to responsive
Example :
<FlatList
style={{
flexGrow: 0,
}}
data={data}
renderItem={({item}) => (
<View>
<Text>{item.text}</Text>
</View>
)}
/>

FlatList has prop contentContainerStyle. You can use it to style wrapper around FlatList. FlatList inherit this prop from ScrollView read hear

you can add flexGrow: 0 to the flatList style worked for me, so it will be:
<FlatList
{...{otherProps}}
style={{
height: 50,
backgroundColor: 'red',
flexGrow: 0
}}
/>

give width then height working according to data
<View style={{maxHeight:"50%",width:"60%"}}>
<FlatList
data={this.props.data}
renderItem={({ item }) => <Text>{item.name}</Text>}
keyExtractor={(item, index) => index}
/>
</View>

<View style={styles.flatList}>
<FlatList
keyExtractor = { this.keyExtractor }
data = { this.getPOs() }
ListEmptyComponent = { this.renderEmpty }
ItemSeparatorComponent = { Separator }
renderItem = { this.renderItem }
/>
</View>
for me works add flex: 1 to the view
const styles = StyleSheet.create({
flatList: {
flex: 1,
}
})

render() {
const listData = [];
listData.push({ key: 0 });
listData.push({ key: 1 });
listData.push({ key: 2 });
listData.push({ key: 3 });
listData.push({ key: 4 });
return (
<View style={styles.container}>
<FlatList
data={listData}
renderItem={({item}) => {
return (
<View
style={{
width: 30, height: 30, borderRadius: 15, backgroundColor: 'green'
}}
/>
)
}}
horizontal
style={styles.flatList}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
height:100
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
},
flatList: {
backgroundColor: 'red'
}
});

Related

KeyboardAwareScrollView has extra bottom padding?

I've had this problem for a while with KeyboardAwareScrollView, where it has some extra padding at the bottom (yellow). Here I want my form to be always at the bottom of the screen, this it seems this padding does not permit this.
export const LoginView: React.FC = () => {
return (
<View style={styles.container}>
<KeyboardAwareScrollView
style={styles.scrollContainer}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
>
<View
style={{
justifyContent: "space-between",
backgroundColor: "green",
}}
>
<View style={styles.imageContainer}>
<Image></Image>
</View>
<View style={styles.formConstainer}>
<Formik></Formik>
</View>
</View>
</KeyboardAwareScrollView>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollContainer: {
backgroundColor: "yellow",
},
imageContainer: {
alignItems: "center",
justifyContent: "center",
},
formConstainer: {},
});
Here's how it looks like right now.
Just change KeyboardAwareScrollView style to contentContainerStyle ( These styles will be applied to the scroll view content container which wraps all of the child views. )
and add flex to view inside it.
export const LoginView: React.FC = () => {
return (
<View style={styles.container}>
<KeyboardAwareScrollView
contentContainerStyle={styles.scrollContainer} //style changed to contentContainerStyle
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
>
<View
style={{
justifyContent: "space-between",
backgroundColor: "green",
flex:1 //flex added
}}
>
<View style={styles.imageContainer}>
<Image></Image>
</View>
<View style={styles.formConstainer}>
<Formik></Formik>
</View>
</View>
</KeyboardAwareScrollView>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollContainer: {
backgroundColor: "yellow",
flexGrow:1 //added flexGrow
},
imageContainer: {
alignItems: "center",
justifyContent: "center",
flex:2 //flex added
},
formConstainer: {
flex:1 //flex added
},
});
Make the contentInset to be dynamic based on the keyboard hide and view.
set the contentBottom value based on your design.
Values in the solution are based on my design
const [contentBottom, setContentBottom] = useState(0);
<KeyboardAwareScrollView
style={{
flex: 1,
backgroundColor: Color.white,
}}
keyboardOpeningTime={0}
extraScrollHeight={150}
enableResetScrollToCoords
onKeyboardWillHide={() => setContentBottom(0)}
onKeyboardWillShow={() => setContentBottom(200)}
contentInset={{ bottom: contentBottom }}
>

How can I connect 2 different flatlist with same data?

I'm trying to achieve when I scroll bigger image, green border on smaller ones will go to the next one. I have 2 different flatlist for this. Tried to write item.key to state with onMomentumScrollEnd but didnt work. Here is my
<FlatList
data={this.state.productImage}
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
onMomentumScrollEnd={item => { this.setState({ active: item.key });
console.log(item.key) }}
renderItem={({ item }) =>
<View>
<Image source={item.source} style={{ width:
Dimensions.get('window').width, height:
Dimensions.get('window').height / 2 }} />
</View>}
keyExtractor={item => item.key}
/>
<FlatList
data={this.state.productImage}
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={{ flexDirection: "row", alignItems: "center",
marginHorizontal: theme.SIZE.pageMargin, marginVertical: 20 }}
renderItem={({ item }) =>
<TouchableOpacity >
<Image source={item.source} style={[this.state.active === item.key
&& styles.activeImage, styles.productImages]} />
</TouchableOpacity>}
keyExtractor={item => item.key}
/>
Edit: After fighting with this I've solved
onMomentumScrollEnd={(event) => {
let xPosition = Math.round(event.nativeEvent.contentOffset.x)
let imageWidth = Math.round(Dimensions.get('window').width)
let keyOfShownImg = (Math.round((xPosition + imageWidth) / imageWidth))
this.setState({ active: keyOfShownImg })
}}
Actually you nearly got the solution. Here you can use onViewableItemChanged prop to achieve this.
I tried out the solution. Take a look here
import * as React from 'react';
import { Text, View, StyleSheet, FlatList, Image } from 'react-native';
import Constants from 'expo-constants';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
visibleIndex: 0,
data: [
'https://homepages.cae.wisc.edu/~ece533/images/airplane.png',
'https://homepages.cae.wisc.edu/~ece533/images/arctichare.png',
'https://homepages.cae.wisc.edu/~ece533/images/arctichare.png',
'https://homepages.cae.wisc.edu/~ece533/images/arctichare.png',
],
};
this.onViewableItemsChanged = this.onViewableItemsChanged.bind(this);
}
renderBigList = ({ item, index }) => {
return (
<Image
style={{ width: 300, height: 300, resizeMode: 'contain' }}
source={{ uri: item }}
/>
);
};
renderSmallList = ({ item, index }) => {
return (
<View
style={{
borderColor:
index === this.state.visibleIndex ? 'green' : 'transparent',
borderRadius: 10,
borderWidth: 2,
margin: 3,
}}>
<Image
style={{ width: 100, height: 100, resizeMode: 'contain' }}
source={{ uri: item }}
/>
</View>
);
};
onViewableItemsChanged = (viewableItemData, changed) => {
//console.log(viewableItemData);
if (viewableItemData.viewableItems.length) {
let keyOfVisibleItem = viewableItemData.viewableItems[0].index;
console.log(keyOfVisibleItem);
this.smallListRef.scrollToIndex({
index: keyOfVisibleItem,
animated: true,
});
this.setState({ visibleIndex: keyOfVisibleItem });
}
};
render() {
return (
<View style={styles.container}>
<FlatList
keyExtractor={(item, index) => '' + index}
style={{ height: '50%' }}
data={this.state.data}
extraData={this.state}
renderItem={this.renderBigList}
horizontal={true}
onViewableItemsChanged={this.onViewableItemsChanged}
viewabilityConfig={{
itemVisiblePercentThreshold: 90,
}}
showsHorizontalScrollIndicator={false}
/>
<FlatList
ref={ref => (this.smallListRef = ref)}
keyExtractor={(item, index) => '' + item}
style={{ height: 50 }}
data={this.state.data}
extraData={this.state}
renderItem={this.renderSmallList}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
padding: 8,
backgroundColor: 'white',
},
});

Last odd flatlist item stretches along screen

I'm displaying some data items with Flatlist in two columns. But when there is an odd item at the last place, it stretches all along the screen. I don't want that, how can I make it to take only %50 of screen space like even items? Thanks a lot.
CategoryGridTile Component:
return (
<View style={styles.PlaceItem}>
<TouchableCmp onPress={props.onSelect}>
<View>
<View style={{ ...styles.placeRow, ...styles.placeHeader }}>
<ImageBackground
source={{ uri: props.image }}
style={styles.bgImage}
>
<View style={styles.titleContainer}>
<Text style={styles.title} numberOfLines={2}>
{props.title}
</Text>
</View>
</ImageBackground>
</View>
</View>
</TouchableCmp>
</View>
)
}
const styles = StyleSheet.create({
PlaceItem: {
flex: 1,
height: 125,
width: '80%',
backgroundColor: '#f5f5f5',
borderRadius: 5,
overflow: 'hidden',
margin: 6
},
placeRow: {
flexDirection: 'row'
}
})
Screen:
const renderGridItem = itemData => {
return (
<CategoryGridTile
image={itemData.item.image}
title={itemData.item.title}
onSelect={() => {
props.navigation.navigate({
routeName: 'CategoryPlaces',
params: {
categoryId: itemData.item.title,
locationId: locations
}
})
}}
/>
)
}
return (
<FlatList
keyExtractor={(item, index) => item._id}
data={displayedCategories}
renderItem={renderGridItem}
numColumns={2}
/>
)
Changing PlaceItem flex: 1 to flex: 1/2 at CategoryGridTile component solved the problem.

How to set the height of the image as the flex height

In my react-native application, I want to set the height of an image as the flex height. How can I do that? At present, Im using the height as the device-heigth / 3. But when it comes to the smaller screens, it makes issues. How can I achieve this as the height of the image as the flex height? My code works properly in 5 inch devices, but when it comes to 4, the image makes a mess.
render() {
return (
<View style={styles.container}>
<View style={styles.postCommentWrapper}>
<ScrollView
ref={view => {
this.scrollView = view;
}}
>
<Animated.View>
<PostProfileBar
profile={this.state.post.author}
timeAgo={this.state.post.timeAgo}
/>
<ClickableImage
source={{ uri: this.state.post.postImage }}
height={height * (3 / 10)}
width={width}
onPress={() => alert("Image Clicked")}
/>
</Animated.View>
<CommentFlatList
data={this.state.data}
refreshing={this.state.refreshing}
/>
</ScrollView>
</View>
<View
style={[
styles.commentInputWrapper,
{ flex: this.state.commentBoxStyles.flex }
]}
>
<InputWithClickableIcon
iconName="upload"
placeholder="Type Comment"
isFocused={true}
fontSize={this.state.comment.value.length > 0 ? 16 : 20}
value={this.state.comment.value}
multiline={true}
maxLength={500}
height={this.state.commentBoxStyles.height}
borderRadius={this.state.commentBoxStyles.borderRadius}
onChangeText={value => this.onChangeComment(value)}
onPress={() => this.uploadComment()}
invalidInput={styles.invalidInput}
valid={this.state.comment.valid}
touched={this.state.comment.touched}
disabled={!this.state.comment.valid}
/>
</View>
</View>
);
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
headerTitle: "Comment",
headerTitleStyle: {
paddingLeft: "20%",
paddingRight: "20%"
},
headerStyle: {
paddingRight: 10,
paddingLeft: 10
},
headerLeft: (
<Icon
name={"close"}
size={30}
onChangeText={this.onChangeText}
onPress={() => {
navigation.goBack();
}}
/>
)
};
};
}
const styles = StyleSheet.create({
container: {
borderWidth: 3,
borderColor: "yellow",
flex: 1
},
postCommentWrapper: {
borderWidth: 2,
borderColor: "blue",
flex: 16,
marginTop: 10
},
// commentListWrapper: {
// borderWidth: 2,
// borderColor: "green",
// flex: 8,
// marginTop: 10
// },
commentInputWrapper: {
flex: 2,
borderWidth: 2,
borderColor: "purple",
justifyContent: "flex-end",
marginTop: 5
}
});
ClickableImage Component
import React from "react";
import { TouchableOpacity, Image, StyleSheet } from "react-native";
const clickableImage = props => (
<TouchableOpacity onPress={props.onPress}>
<Image
{...props}
style={[
styles.image,
props.style,
{ height: props.height },
{ width: props.width }
]}
/>
</TouchableOpacity>
);
const styles = StyleSheet.create({
image: {
marginTop: 10,
flexDirection: "row",
alignItems: "center"
}
});
export default clickableImage;
Since you've already passed the style props to the ClickableImage, therefore you can do
<ClickableImage
source={{ uri: this.state.post.postImage }}
style={{flex: 1}}
onPress={() => alert("Image Clicked")}
/>
You also need to pass the styles to TouchableOpacity for the flex inside the container to work
<TouchableOpacity style={props.style} onPress={props.onPress}> //... Pass the relevant styles here

implement tabs in the center of the screen

I am new to react native. i have implemented stacknavigator inside drawernavigator. Using this library
"react-navigation": "^1.0.0-beta.11",
Now i want to implement tabs within the screen at the center. Following image is part of my screen
i dont have any idea how can i do this with any library or manually putting views.
Any help is appreciated.
Thanks
Well, I've solved that scenario using react-native-swiper
Basically you have to wrap all views you want to have inside a Swiper, render and style the header as you want.
Here there is a working example I've made:
render() {
return (
<View style={styles.body}>
<Swiper
height={500}
showsPagination={true}
loop={false}
renderPagination={this._renderPagination}
ref={component => this._swiper = component}>
<View style={styles.page}>
<FlatList data={..} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
<View style={styles.page}>
<FlatList data={...} renderItem={item => ...} keyExtractor={(item, index) => index} />
</View>
</Swiper>
</View>
);
}
_renderPagination(index, total, context) {
return (
<View style={styles.pagination}>
{this._renderPaginationHeaders(index, total, context)}
</View>
)
}
_renderPaginationHeaders(index, total, context) {
let ret = [];
for (let i = 0; i < total; i++) {
ret.push(
<TouchableOpacity key={i} style={{ flex: 1, flexDirection: 'column' }} onPress={() => this._onPageChange(i)}>
<Text style={[styles.title, { flex: 1, textAlign: 'center', textAlignVertical: 'center' }]}>
{this._getSectionText(i)}
</Text>
<View style={{ height: 5, backgroundColor: index === i ? 'magenta' : 'transparent' }}></View>
</TouchableOpacity>
);
}
return ret;
}
_onPageChange(targetIndex) {
const currentIndex = this._swiper.state.index;
const offset = targetIndex - currentIndex;
this._swiper.scrollBy(offset);
}
const styles = StyleSheet.create({
body: {
flex: 1,
alignItems: 'center',
alignSelf: 'center',
backgroundColor: '#f1f1f1',
},
pagination: {
flexDirection: 'row',
width: Dimensions.get('window').width,
height: Header.currentHeight * 0.7,
backgroundColor: '#2E2E2E',
paddingLeft: 2,
paddingRight: 2,
alignItems: 'center',
position: 'absolute',
top: 0,
},
page: {
flex: 1,
marginTop: (Header.currentHeight * 0.7) + 3
},
title: {
color: 'white'
},
});