Related
I'm using a flatlist with rowNumber={4} and I want to display some elements with a Width-max.
But I got this result :
As you can see some elements protrude on the left side. How can I make it fit automatically ?
Expected result :
There is my code :
<SafeAreaView>
<View
style={{
height: "100%",
maxWidth: "100%",
right: "10%",
}}
>
<FlatList
style={{width: "120%"}}
data={brands}
numColumns={4}
keyExtractor={(_, item) => item}
renderItem={({item}) => (
<View style={styles.card} key={item["id"]}>
<TouchableOpacity
onPress={() => {
var index = brandId.indexOf(item["id"]);
if (index > -1) {
brandId.splice(index, 1);
cpt = cpt - 1;
} else {
brandId.push(item["id"]);
cpt = cpt + 1;
}
console.log("ici ! ", cpt);
console.log("Il existe deja bro", brandId);
}}
>
<Text style={styles.text}>{item["name"]}</Text>
</TouchableOpacity>
</View>
)}
/>
</View>
</SafeAreaView>
CSS :
card: {
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
},
text: {
paddingRight: "2%",
textAlign: "center",
width: "100%",
fontSize: 12,
color: "black",
},
don't use flatlist. with flatlist you will always have fixed numberOfColumns but your item widths could be diff from each other. use map instead inside scrollview.
updated code :
<View style={[{ flexDirection: 'row', flexWrap: 'wrap' }]}>
{brands.map(element => {
return <View style={styles.card}>
<Text>{element.name}</Text>
</View>
})
}
</View>
styles:
card: {
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
paddingHorizontal: 5
},
Modify style of card:
card: {
flex:1,
flexDirection:"row"
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
},
or If you don't use flatlist then below code will solve your issue:
<View style={[{flexDirection: 'row', flexWrap: ' wrap'}]}>
data.map(element => {
return <Text style={{height:100}}>element.content</Text>
})
</View>
I want to achieve this animation using section list on scroll in react native.
Here is an example of food panda. This is their initial screen:
On scrolling the section list their header collapse and it becomes like this:
Here is the code of my RestaurantDetail screen:
export default function RestaurantDetail({navigation, route}) {
const headerHeight = 400;
const headerFinalHeight = 100;
const scrollY = useRef(new Animated.Value(0)).current;
const offset = headerHeight - headerFinalHeight;
const translateHeader = scrollY.interpolate({
inputRange: [0, offset],
outputRange: [0, -offset],
extrapolate: 'clamp',
});
useEffect(() => {
return navigation.addListener('focus', () => {
getRestaurantDetail();
if (user) {
getCart();
}
});
}, []);
const onScrollY = e => {
scrollY.setValue(e.nativeEvent.contentOffset.y);
headerHeight - e.nativeEvent.contentOffset.y;
console.log('Height', scrollY);
};
const onScroll = ({viewableItems}) => {
setActiveTab(viewableItems[0].section.title);
console.log('viewableItems', viewableItems[0].section.title);
};
return (
<View style={{backgroundColor: 'white', flex: 1}}>
<Animated.View
style={{
backgroundColor: 'white',
height: headerHeight,
position: 'absolute',
transform: [{translateY: translateHeader}],
}}>
<Header restaurantDetail={detail} />
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<MainImage restaurantDetail={detail} />
<TouchableOpacity
onPress={() => navigation.navigate('RestaurantInfo', detail)}>
<Rating />
</TouchableOpacity>
</View>
<TouchableOpacity
onPress={() => navigation.navigate('RestaurantInfo', detail)}>
<Title restaurantDetail={detail} />
</TouchableOpacity>
<HeaderTabs
activeTab={activeTab}
setActiveTab={setActiveTab}
data={itemList}
ref={ref}
/>
</Animated.View>
<View style={{paddingTop: headerHeight}}>
<SectionListeg
restaurantDetail={detail}
activeTab={activeTab}
setActiveTab={setActiveTab}
navigation={navigation}
onScroll={onScroll}
onScrollY={onScrollY}
data={itemList}
scrollEventThrottle={16}
/>
</View>
{showView && (
<View style={styles.box}>
<View style={styles.viewCartView}>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => navigation.navigate('Cart', true)}>
<View style={styles.viewCartBtn}>
<View style={styles.counterView}>
<Text style={styles.text}>
{cart.cart ? cart.cart.length : cart.length}
</Text>
</View>
<Text style={styles.text}>View your cart</Text>
<Text style={styles.text}>{'Rs. ' + cart.sub_total}</Text>
</View>
</TouchableOpacity>
</View>
</View>
)}
<SafeAreaView
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: transparent ? 'transparent' : 'white',
}}>
<TopBar navigation={navigation} shouldShow={shouldShow} name={name} />
</SafeAreaView>
</View>
);
}
const styles = StyleSheet.create({
viewCartView: {
width: '100%',
height: 100,
backgroundColor: 'white',
position: 'absolute',
bottom: 0,
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
alignItems: 'center',
justifyContent: 'center',
elevation: 5,
},
headerContainer: {
// position: 'absolute',
},
box: {
// ...
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 1.0,
shadowRadius: 3,
elevation: 5,
},
viewCartBtn: {
width: '90%',
height: 50,
backgroundColor: Colors.secondary,
alignSelf: 'center',
borderRadius: 10,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-evenly',
},
counterView: {
width: 30,
height: 30,
borderRadius: 50,
borderWidth: 1.5,
borderColor: 'white',
justifyContent: 'center',
alignItems: 'center',
},
text: {color: 'white', fontSize: 16, fontWeight: '700'},
});
Here is the code of my Section List:
const SectionListeg = ({
navigation,
onScroll,
data,
scrollEventThrottle,
activeTab,
onScrollY,
setIndex,
setActiveTab,
restaurantDetail,
shouldShow,
branchId,
}) => {
const headerHeight = 400;
const headerFinalHeight = 100;
const offset = headerHeight - headerFinalHeight;
const scrollY = useRef(new Animated.Value(0)).current;
const translateHeader = scrollY.interpolate({
inputRange: [0, offset],
outputRange: [0, -offset],
extrapolate: 'clamp',
});
const renderItem = ({item, index}) => {
return (
<Item
item={item}
navigation={navigation}
restaurantDetail={restaurantDetail}
/>
);
};
return (
<SectionList
sections={data}
showsVerticalScrollIndicator={false}
scrollEnabled={true}
keyExtractor={(item, index) => {
// console.log('Key Index', item.title);
if (item.id) {
return item.id;
}
}}
renderItem={renderItem}
onViewableItemsChanged={onScroll}
onScroll={onScrollY}
stickySectionHeadersEnabled={false}
renderSectionHeader={({section: {title}}) => (
<Text style={styles.header}>{title}</Text>
)}
/>
);
};
const Item = ({item, navigation, restaurantDetail}) => (
<View style={styles.item}>
<TouchableOpacity
activeOpacity={0.7}
style={{flexDirection: 'row', width: '100%'}}
onPress={() => onItemPress(item, navigation, restaurantDetail)}>
<View style={{flexDirection: 'row'}}>
<View style={{width: '70%'}}>
<Text style={styles.title}>{item.title}</Text>
<Text numberOfLines={2} style={styles.description}>
{item.description}
</Text>
<Text style={{marginTop: 5, color: Colors.black}}>
PKR {item.price}
</Text>
</View>
<View style={{width: '30%'}}>
<Image
style={styles.image}
source={{uri: 'https://uat.yallafood.pk/' + item.imageUrl}}
/>
</View>
</View>
<View
style={{
width: '100%',
height: 1,
position: 'absolute',
bottom: 0,
left: 0,
backgroundColor: Colors.grey,
}}
/>
</TouchableOpacity>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
marginHorizontal: 16,
},
item: {
backgroundColor: '#fff',
marginVertical: 5,
paddingStart: 20,
paddingEnd: 20,
flexDirection: 'row',
justifyContent: 'space-between',
},
header: {
fontSize: 26,
backgroundColor: '#fff',
marginLeft: 20,
fontWeight: 'bold',
color: 'black',
},
title: {
fontSize: 20,
color: 'black',
},
description: {
fontSize: 14,
color: Colors.grey,
marginTop: 5,
// width: '50%',
},
image: {
width: 80,
height: 80,
borderRadius: 10,
marginBottom: 10,
alignSelf: 'flex-end',
},
});
This is my initial Screen:
This is my screen on Scroll:
Any help will be appreciated.
I want to print this data on my mobile screen but it shows me nothing when I write the code from this response:
This is my code:
const [data, setData] = useState('')
useEffect(() => {
getData()
}, [])
const getData = async () => {
fetch(`${urldemo}blog/${slug}?token=${user_token}`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then((response) => response.json())
.then((responseJson) => {
setLoading(false);
setData([...data, ...responseJson.result]);
console.log("log for Exploreblogs =====>", responseJson.result)
})
.catch((error) => {
console.error(error);
});
}
This is my return code where I am stuck:
const renderItem = ({ item }) => {
return (
<ScrollView style={[styles.footer, {
backgroundColor: "white"
// colors.background
}]}>
<Card style={{ marginHorizontal: 20, }}>
<Card.Cover style={{ marginVertical: 10, borderRadius: 10, height: 200, }}
source={require('../../../assets/imagehere.png')} />
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Image
source={require('../../../assets/news9.png')} />
<Text style={{ textAlign: 'right', color: "orange" }}>
{item.short_description}
</Text>
</View>
<Text style={{ textAlign: 'center', color: "black", fontSize: 24 }}>
{item.description}
</Text>
<View style={{
justifyContent: "space-between",
flexDirection: "row",
marginHorizontal: 10
}}>
<View style={{ flexDirection: "row" }}>
<Text style={{ color: "green" }}>4hrs ago</Text>
<Text style={{ color: "green" }}> ~ 5 min read</Text>
</View>
<View style={{ flexDirection: "row" }}>
<Image
source={require('../../../assets/comment.png')} />
<Image style={{ marginHorizontal: 10 }}
source={require('../../../assets/shae.png')} />
<Image
source={require('../../../assets/saved.png')} />
</View>
</View>
</Card>
{/* <Text style={{
textAlign: 'left', color: "grey", fontSize: 16,
marginHorizontal: 20, marginVertical: 20
}}>
{item.title}
</Text> */}
<Image style={{ marginHorizontal: 20, width: "90%", borderRadius: 10 }}
source={require('../../../assets/exnews.png')} />
<Text style={{ marginHorizontal: 20 }}>{item.description}</Text>
<Text style={{
textAlign: 'left', color: "grey", fontSize: 16,
marginHorizontal: 20, marginVertical: 20
}}>
{item.short_description}
</Text>
</ScrollView>
);
}
return (
<TouchableOpacity >
{/* <BlogsHeader />
*/}
<Animatable.View
animation="zoomIn" >
<View style={{
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
backgroundColor: 'white',
height: 45,
}}>
<TouchableOpacity onPress={() => navigation.navigate('Blogs')}>
<Image style={{
color: 'black',
marginTop: 15,
tintColor: 'orange'
}}
source={require('../../../assets/backicon.png')}
/>
</TouchableOpacity>
<Text style={{
fontSize: 15,
color: '#FF7F23',
textAlign: "center",
marginTop: 15,
}}
> Blogs</Text>
<Image style={{ color: 'black', marginTop: 15, alignSelf: 'center', }}
source={require('../../../assets/avatar.png')}
/>
</View>
{isLoading ? <ActivityIndicator size="large" color="#FF8025" /> : (
<FlatList
style={styles.container}
data={data}
renderItem={renderItem}
keyExtractor={(item, index) => index.toString()}
/>
)
}
</Animatable.View>
</TouchableOpacity>
)
I have used Flatlist for Item.
I just want to print my response data on my mobile screen but it didn't
work for me
I get following error message in the console output:
[TypeError: Invalid attempt to spread non-iterable instance. In order to be iterable, non-array objects must have a Symbol.iterator method.]
The problem is with this line:
setData([...data, ...responseJson.result]);
I'm assuming responseJson.result is an object, in which case this won't work since you can't spread an object into an array, at least in the way you intend.
This should work for you though:
const [data, setData] = useState({}) // Use object instead
// Other stuff
setData({...data, ...responseJson.result}); // Spread to object instead.
Alternatively, consider checking out these solutions e.g. for...of or Object.keys()/entries()/....
Otherwise, you would need to post the value responseJson.result for more troubleshooting.
Cannot figure out why I keep getting a ReferenceError cant find variable MarkAsRead for a mobile app I am building in react. Unless I am missing something the variable has been assigned below is the code for your reference. Hopefully, someone can help me get this bug resolved in a timely matter thanks in advance!
import React from 'react';
import { View,
Text,
StyleSheet,
SafeAreaView,
TouchableOpacity,
TextInput,
FlatList
} from 'react-native';
import BookCount from './components/BookCount';
import {Ionicons} from '#expo/vector-icons';
class App extends React.Component {
constructor() {
super()
this.state = {
totalCount: 0,
readingCount: 0,
readCount: 0,
isAddNewBookVisible:false,
textInputData: '',
books: [],
bookData: {
author: '',
publisher: ''
}
};
}
showAddNewBook = () => {
this.setState({isAddNewBookVisible:true});
};
hideAddNewBook = () => {
this.setState({isAddNewBookVisible:false})
};
addBook = book => {
this.setState(
(state, props) => ({
books: [...state.books, book],
totalCount: state.totalCount + 1,
readingCount:state.readingCount + 1,
isAddNewBookVisible: false
}),
() => {
console.log(this.state);
}
);
};
markAsRead = (selectedBook, index) => {
let newList = this.state.books.filter(book => book !==
selectedBook);
this.setState(prevState => ({
books: newList,
readingCount: prevState.readingCount - 1,
readCount: prevState.readCount + 1
}));
};
renderItem = (item, index) => (
<View style={{ height:50, flexDirection: 'row'}}>
<View style={{ flex:1, justifyContent: 'center', paddingLeft: 5
}}>
<Text>{item}</Text>
</View>
<TouchableOpacity onPress={() => markAsRead(item,index)} >
<View
style={{
width: 100,
height: 50,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#160b1a'
}}
>
<Text style={{ fontWeight: 'bold', color: 'white'}}>Mark as Read</Text>
</View>
</TouchableOpacity>
</View>
);
render() {
return (
<View style={{flex: 1}}>
<SafeAreaView/>
<View style={{
height: 70,
borderBottomWidth: 0.5,
borderBottomColor: '#5e3c7d',
alignItems: 'center',
justifyContent: 'center'
}}
>
<Text style={{fontSize: 24}}>VekTorfy AI</Text>
</View>
<View style={{ flex: 1}}>
{this.state.isAddNewBookVisible &&
<View style={{height:50, flexDirection: 'row'}}>
<TextInput
onChangeText={(text)=>this.setState({textInputData:text})}
style={{ flex:1, backgroundColor: '#c6c0cb',
paddingLeft: 5}}
placeholder='Enter book name.'
placeholderTextColor='black'
/>
<TouchableOpacity
onPress={() => this.addBook(this.state.textInputData)} >
<View style={{
width: 50,
height: 50,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#160b1a'}}>
<Ionicons name ='ios-checkmark' color='white' size={40}/>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={this.hideAddNewBook}>
<View style={{
width: 50,
height: 50,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#160b1a'}}>
<Ionicons name ='ios-close' color='red' size={40}/>
</View>
</TouchableOpacity>
</View>
}
<FlatList
data={this.state.books}
renderItem={({item}, index) => this.renderItem(item, index)}
keyExtractor={(item, index)=> index.toString()}
ListEmptyComponent={
<View style={{marginTop: 50, alignItems: 'center'}}>
<Text style={{fontWeight: 'bold'}}>Not Reading anything.</Text>
</View>
}
/>
<TouchableOpacity
onPress={this.showAddNewBook}
style={{position: 'absolute', bottom: 20, right: 20}}>
<View
style={{
width:50,
heght:50,
alignItems: 'center',
justifyContent: 'center',
borderRadius:25,
backgroundColor: '#2d2337'}}>
<Text style={{color: 'white', fontSize: 30}}>+</Text>
</View></TouchableOpacity>
</View>
<View
style={{
height: 70,
flexDirection: 'row',
borderTopWidth: 0.5,
borderTopColor: '#5e3c7d' }}>
<BookCount title='Total' count={this.state.totalCount}/>
<BookCount title='Reading' count={this.state.readingCount}/>
<BookCount title='Read' count={this.state.readCount}/>
</View>
<SafeAreaView/>
</View>
);
}
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
You forgot to add the keyword this to your function call.
<TouchableOpacity onPress={() => this.markAsRead(item,index)}>
It looks like you have declared markAsRead as a method on your App class, so the correct way to refer to it is this.markAsRead()
<TouchableOpacity onPress={() => this.markAsRead(item, index)}>
On my android phone, I can only select the first choice in the autocomplete list. It works as expected on my iPhone. The list filters as I type but no matter what the first option is after filtering, I can only select the first option in the list. I tried adding a "console.log" to the touchables in the list to see if the other options are registering the touch event and they aren't. Without giving away too much of my code it is as follows:
<ScrollView contentContainerStyle={[formStyles.container]} scrollEventThrottle={64} keyboardDismissMode="on-drag" onScroll={() => { if(!this.state.hideResults){this.setState({hideResults:true})}}}>
<KeyboardAvoidingView behavior={"padding"}>
<View style={AddViewInviteeStyles.inviteeInputMainView}>
<Text style={AddViewInviteeStyles.inviteeInputInstructionText}>{this.state.contactsRetrieved ? retrievedContactText : noRetrievedContactText}</Text>
<View style={[AddViewInviteeStyles.inviteeInputAutocompleteView]}>
<AutoComplete style={[AddViewInviteeStyles.inviteeInputAutocomplete, this.state.invalidContact ? {backgroundColor : '#dd4f42'} : {}]}
data={this.state.contacts}
value={typeof this.state.invitee === "string" ? this.state.invitee : this.state.invitee.name}
containerStyle={[textStyles.container, {width: textStyles.textboxes.width}]}
placeholder={"Invite someone"}
placeholderTextColor={textStyles.datePickerTextStyle.color}
ref={(ref) => this.inviteeControl = ref}
hideResults={this.state.hideResults}
inputContainerStyle={[textStyles.container, {width: '100%', borderWidth: 0}]}
onChangeText={(text) => {
this.setState({ invitee: text });
if(this.state.invalidContact){
this.validateContact();
}
this.filterContacts(text);
}}
renderItem={({ item, i }) => (
<TouchableOpacity onPress={() => {this.setState({ invitee: item, hideResults:true, invalidContact: false })}} style={[{width: "100%"}, i > 0 ? {marginTop: 10} : {}]}>
<Text numberOfLines={1} ellipsizeMode={"tail"} style={{fontSize: responsiveFontSize(2)}}>{item.name}</Text>
</TouchableOpacity>
)}
listStyle={[{width: '100%', position: 'relative'}]}
keyExtractor={(item, i) => {return i +""}}
listContainerStyle={[textStyles.container, {width: responsiveWidth(parseInt(textStyles.textboxes.width.replace('%', ''))), position:'absolute', left: 0, top: textStyles.textboxes.height, justifyContent: 'center', alignItems: 'center', zIndex:300}]}
autoFocus={true}
blurOnSubmit={false}
underlineColorAndroid='transparent'
/>
<TouchableOpacity activeOpacity={1} style={[{width: this.state.addNewInvitee ? '10%':'20%', ...Util.filterObject(textStyles.textboxes, ["width", "minWidth"])}, !this.state.addNewInvitee? textStyles.lastTextBoxInFirstRow : {}, !this.state.addNewInvitee? textStyles.lastTextBoxInLastRow : {}, this.state.invalidContact ? {backgroundColor : '#dd4f42'} : {}]} onPress={this.addInvitee.bind(this)}>
{!this.state.invalidContact ? <Text style={[{fontSize: this.state.addNewInvitee ? responsiveFontSize(3) : responsiveFontSize(4), alignContent: 'center', justifyContent: 'center', textAlign:'center', textAlignVertical: 'center', marginTop: this.state.addNewInvitee? 11: 5}, this.state.addNewInvitee ? {marginRight: 2} : {}]}><Emoji name={"heavy_plus_sign"} /></Text> : null}
</TouchableOpacity>
{this.state.addNewInvitee ? addNewInviteeCancelBtn : null}
</View>
{this.state.invalidContact ? invalidInviteeText : null}
</View>
</KeyboardAvoidingView>
</ScrollView>
const AddViewInviteeStyles = StyleSheet.create({
inviteeInputMainView: {
alignItems: 'center',
marginTop: 40,
marginBottom: 20
},
inviteeInputInstructionText: {
...textStyles.requiredNotice,
...textStyles.notifyTextStyle,
fontSize: responsiveFontSize(2),
...Platform.select({
android:{
width: responsiveWidth(90)
}
})
},
inviteeInputAutocompleteView:{
...textStyles.container,
flexDirection: 'row',
...Platform.select({
android: {
width: responsiveWidth(parseInt(textStyles.textboxes.width.replace('%' , ''))),
},
ios:{
width: textStyles.textboxes.width
}
})
},
inviteeInputAutocomplete: {
...textStyles.textboxes,
...textStyles.firstTextBoxInFirstRow,
...textStyles.firstTextBoxInLastRow,
width: '100%'
}
});
const formStyles = StyleSheet.create({
container: {
...appStyles.container,
flexGrow: 1,
width: '100%',
}
});
const appStyles = StyleSheet.create({
container: {
backgroundColor: '#e9dec2',
}
});
const textStyles = StyleSheet.create({
container: {
alignItems: 'center',
},
textboxes: {
color: '#3c3b5f',
backgroundColor: '#F0F8FF',
width: '80%',
paddingLeft: 5,
paddingRight: 2,
minHeight: 35,
height: 50,
borderBottomColor: '#fbdd07',
borderBottomWidth: 1,
},
requiredNotice: {
color: 'grey',
fontSize: 13,
marginTop: 70,
},
firstTextBox: {
marginTop: 70,
borderTopLeftRadius: 8,
borderTopRightRadius: 8
},
firstTextBoxInFirstRow: {
borderTopLeftRadius: 8,
},
lastTextBoxInFirstRow: {
borderTopRightRadius: 8,
},
firstTextBoxWithNotice: {
borderTopLeftRadius: 8,
borderTopRightRadius: 8
},
textBoxInRow: {
borderRightWidth: 1,
borderBottomColor: '#fbdd07',
//borderRightColor: '#fbdd07'
},
notifyTextStyle: {
marginTop: '7%',
fontSize: responsiveFontSize(4),
fontWeight: "300"
}
})