How can I use this with FlatList not with ListView? - ios

I took this code from react-native-gifted-chat
and I want to use FlatList
<ListView
enableEmptySections={true}
automaticallyAdjustContentInsets={false}
initialListSize={20}
pageSize={20}
{...this.props.listViewProps}
dataSource={this.state.dataSource}
renderRow={this.renderRow}
renderHeader={this.renderFooter}
renderFooter={this.renderLoadEarlier}
renderScrollComponent={this.renderScrollComponent}
/>

Here's an example for using FlatList to do what you're trying to do:
render() {
return (
<View style={{ flex: 1 }}>
<FlatList
data={someArrayWithDataObjects} // your data source
renderItem={({ item }) => this.renderSearchResults(item)} // how you want each item rendered
keyExtractor={item => item.id} // unique identifier for performance reasons
/>
</View>
);
}

Related

FlatList item click is not rendering this

export default class HistoryScreen extends BaseScreen {
constructor(props){
super(props);
this.state = {
mainListData:[],
listData:[],
searchText:'',
};
}
listRowPressed(item) {
this.props.navigation.navigate('Details', {
checkin: item.data
});
}
render() {
return (
<View style={styles.container}>
<View style={{ flex:1, backgroundColor: '#FFF'}}>
<FlatList
data={this.state.listData}
renderItem={({item}) => <ListComp data={item} />}
keyExtractor={(item, index) => index.toString()}
/>
</View>
</View>
);
}
}
const ListComp = item => (
<TouchableOpacity onPress={() => this.listRowPressed(item)
}>
<View style={styles.row}>
</View>
</TouchableOpacity>
);
I am displaying data in FlatList, however clicking on item gives me this4. listRowPressed is undefined, I tried binding the function too but didn't work. What is wrong in the code?
You have to pass listRowPressed in your ListComp component. Your whole code should be like this :
export default class HistoryScreen extends BaseScreen {
constructor(props) {
super(props);
this.state = {
mainListData: [],
listData: [],
searchText: '',
};
}
listRowPressed = (item) => {
this.props.navigation.navigate('Details', {
checkin: item.data
});
}
render() {
return (
<View style={styles.container}>
<View style={{ flex: 1, backgroundColor: '#FFF' }}>
<FlatList
data={this.state.listData}
renderItem={({ item }) => <ListComp data={item} listRowPressed={this.listRowPressed} />}
keyExtractor={(item, index) => index.toString()}
/>
</View>
</View>
);
}
}
const ListComp = (props) => (
<TouchableOpacity
onPress={() => props.listRowPressed(props.item)}
>
<View style={styles.row}>
{/* Do whatever with props.item here */}
</View>
</TouchableOpacity>
);
Also note that I have converted your method listRowPressed simple function to arrow function.
Try this
<FlatList
data={this.state.listData}
renderItem={this.listComp}
keyExtractor={(item, index) => index.toString()}
/>
listComp = ({item}) => (
return(
<TouchableOpacity onPress={() => this.listRowPressed(item)} >
<View style={styles.row}>
</View>
</TouchableOpacity>
);
);

How to use KeyboardAvoidingView with FlatList?

I have a FlatList component with an Input inside each row. When I select the input I want it to scroll up above the keyboard.
My code:
return (
<KeyboardAvoidingView behavior='padding' style={{ flex: 1 }} >
<FlatList
style={{ flex: 1, backgroundColor: '#fff' }}
data={ds}
renderItem={({ item }) => <ListItem data={item} />}
ListFooterComponent={this.renderButton}
/>
</KeyboardAvoidingView>
);
In this scenario, the FlatList is never loaded. When I delete flex:1 from both components, FlatList renders properly but selecting an Input does not make it scroll up
You can trying using react-native-keyboard-aware-scroll-view
https://github.com/APSL/react-native-keyboard-aware-scroll-view
It comes with KeyboardAware[ScrollView, ListView, SectionView, FlatList] which accepts the same props as their corresponding components from RN. I have used that and it worked for me.
render() {
return (
<KeyboardAwareFlatList
style={{flex: 1}}
data={this.state.data}
renderItem={({item}) => (
<View style={{flex: 1}}>
<Image
source={item.v}
style={{height:200, width: 200}}
/>
<TextInput
placeholder="enter text1"
/>
</View>
)}
/>
);
}
You could try using the library react-native-keyboard-spacer as an alternative to KeyboardAvoidingView.
Install:
npm install --save react-native-keyboard-spacer
Use it like this:
import KeyboardSpacer from 'react-native-keyboard-spacer'
...
<View style={{flex: 1}}>
<FlatList
style={{flex: 1}}
data={ds}
renderItem={({ item }) => <ListItem data={item} />}
/>
{/* The view that will expand to match the keyboard height */}
<KeyboardSpacer />
</View>
Try this:
<KeyboardAvoidingView behavior='position' keyboardVerticalOffset={xyz} >
You can remove the property 'keyboardVerticalOffset' or play with the value of xyz,
just find out the better value which fits in your case.
For anyone on a similar path as mine. I was not able to use KeyboardAvoidingView because it depends on ScrollView which conflicts with Flatlist. I couldn't used the header and footer option in Flatlist as I'm using it as a generated thing in a search selection box so it has to be contained.
For me there is a difference in how Android and iOS calculate absolute position. Android considers the bottom to be the top of the keyboard and iOS it is the bottom of the screen when the keyboard is showing.
It turns out to be not that difficult to just put a View around the content you want to remain above the keyboard and just dynamically set the height of it on iOS. This isn't even really necessary on Android as it follows the keyboard if the View is position: absolute and bottom: 0.
This heavily borrows from here: https://stackoverflow.com/a/60682069/438322
Thanks to Kevin Amiranoff
Here's a basic example using hooks.
function YourComponent(props){
const onKeyboardWillShow = e => {
setKeyboardHeight(e.endCoordinates.height);
};
const onKeyboardWillHide = () => {
setKeyboardHeight(0);
};
useEffect(() => {
// These listeners on ios are a little more snappy but not available on Android
// If you want to use this on Android use keyboardDidShow/Hide
if (Platform.OS === 'ios') {
Keyboard.addListener('keyboardWillShow', onKeyboardWillShow);
Keyboard.addListener('keyboardWillHide', onKeyboardWillHide);
}
return () => {
if (Platform.OS === 'ios') {
Keyboard.removeListener('keyboardWillShow', onKeyboardWillShow);
Keyboard.removeListener('keyboardWillHide', onKeyboardWillHide);
}
};
}, []);
const buttonHeight = 50;
return(
<View>
<Content bla={'bla'}/>
<View style={{
height: Platform.OS === 'ios'
? keyboardHeight + buttonHeight : buttonHeight,
position: 'absolute',
bottom: 0
}}>
{/* Keep this button above the keyboard */}
<Button style={{ height: buttonHeight }}/>
</View
</View>
)
}
this is my solution.
inverted={true} is the key
const dummy = [1,2,3,4,5,6,7,8,9,10]
<KeyboardAvoidingView >
<FlatList
data={dummy.reverse()}
inverted={true}
/>
</KeyboardAvoidingView>

How did I use the push() function in NavigatorIOS?

I want to Push to a new Component by the function push() in NavigatorIOS. It's like following:
renderRow(rowData, sectionID, rowID) {
var imgSource = IMAGE_URLS[rowID];
return (
<TouchableHighlight onPress = {() => {
this.props.navigator.push({
title: 'test',
component: example,
});
}}>
<View>
<View style={styles.row}>
<Image
source={imgSource}
style={styles.thum}
/>
<Text style={styles.text}>
{rowData}
</Text>
</View>
</View>
</TouchableHighlight>
);
}
But it will get a error when I click the TouchableHighlight.
I refered these two questions(1 and 2) before this. And the complete code is in this link
this is not binded to the class inside of renderRow().
You have to bind this either in the constructor:
this.renderRow = this.renderRow.bind(this);
or inside the render method:
render() {
var navStatusBarConfig = {
style: 'light-content',
}
return (
<View style={{ flex: 1, backgroundColor: '#F5FCFF'}}>
<View styles={styles.nav}></View>
<ListView
automaticallyAdjustContentInsets={false}
contentContainerStyle={styles.list}
dataSource={this.state.dataSource}
pageSize={4}
renderRow={this.renderRow.bind(this)}
/>
</View>
);
}
}
As to why, here is the reason :
https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding
And a more complete blog about how to bind this [there are many, blogs and ways to bind this]) :
http://blog.andrewray.me/react-es6-autobinding-and-createclass/

React-Native RefreshControl displaces Sticky Header iOS

Having an issue inside a ListView that uses sticky headers. When I scroll down while the refresh is still occurring, my sticky header is shifted down roughly equal to the height of the refresh control.
Any idea what's causing this?
Here is the code for my ListView and the refreshControl:
<View style={{backgroundColor: Colors.stickyHeaderGray, height: SCREEN_HEIGHT-20}}>
<ListView
ref='list'
style={this.container}
dataSource={this.state.ds}
initialListSize={12}
scrollRenderAheadDistance={0}
onEndReached={() => this.setState({ hideLoadingFooter: true })}
onEndReachedThreshold={10}
pageSize={10}
renderRow={(data) => <FeedItem {...data} navigator={this.props.navigator} />}
renderSeparator={this._renderSeparator}
renderSectionHeader={(sectionData, sectionID) =>
<View style={{backgroundColor: Colors.stickyHeaderGray, opacity: 0.96}}>
<TouchableHighlight
onPress={() => this.refs.list.scrollTo({x:0,y:0,animated:true})}
underlayColor={Colors.stickyHeaderGray}>
<View>
<Heading1 style={styles.headers}>{sectionID}
</Heading1>
</View>
</TouchableHighlight>
</View>
}
renderFooter={() =>
this.state.hideLoadingFooter ? null : <View style={styles.footer}><Heading1>Loading </Heading1><Spinner type={'ThreeBounce'} size={40} color={Colors.wabashRed} isVisible={true} /></View>
}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
tintColor={Colors.charcoal}
/>
}
/>
</View>

React-native: Why rendering an empty view component creates an error while a text component runs?

I am trying to create an array of View components in react-native that are passed to a parent component. The code below does not work, however if i use Text instead of View it works. I want use view to show empty or filled circles. I couldn't find the reason for it and i assume it should be possible to use an empty view. What am i doing wrong?
class card extends React.Component {
renderScore(balance, fulfill, markImage){
var scores = [];
for (i = 1; i <= fulfill; i++) {
if(i<=balance){
if (markImage) {
scores.push(<View style={styles.emptyCircle} key={i}> </View>);
//scores.push(<View style={styles.emptyCircle} key={i}> <Image source={{uri: markImage}} style={styles.markImage}/> </View>);
}
else{
scores.push(<View style={styles.emptyCircle} key={i}> <View style={styles.punchCircle}></View> </View>);
}
}
else
{
scores.push(<View style={styles.emptyCircle} key={i}> </View>);
}
}
return(scores);
}
}
This will give 'RawText " " must be wrapped in an explicit component.'
However if use
scores.push(<Text style={styles.emptyCircle} key={i}> </Text>);
it works.
It is called from a ListView as
_renderCard(item){
var cardBottom = new cardRenderer();
var childView = cardBottom.renderScore(item.balance, item.fulfill, item.markImage);
console.log(childView);
return(
<View style={styles.mainConatiner}>
<View style={styles.leftConatiner}>
<Image
source={{uri: item.avatarLeft}}
style={styles.thumbnail}
/>
</View>
<View style={styles.rightConatiner}>
<View style={styles.rightUpConatiner}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.title}>{item.subTitle}</Text>
<Text style={styles.title}>{item.expires}</Text>
</View>
<View style={styles.rightDownConatiner}>{childView}</View>
</View>
</View>
);
}
Use below for empty view
return(<></>)
try this
return(<View>{scores}</View>);

Resources