在react-native中实现双向无限ScrellView

时间:2017-12-08 05:19:28

标签: react-native infinite-scroll

我想在这两个方向上实现无限滚动视图。还应该动态加载数据。

我使用 SectionList 组件作为列表。我实现了前进无限滚动。这意味着如果用户向下滚动,数据将自动附加到列表中。

为此,我使用了 onMomentumScrollEnd 事件。当用户停止滚动时,如果滚动处于向上方向,则数据将附加在结束处,如果滚动处于向下方向,则数据将附加在顶部。

现在问题是当我将数据附加到列表顶部时,它将所有当前列表数据向后移动。即使数据已更新,我也不想转移当前列表。有没有办法做到这一点。

这是我的代码:

import React, {Component} from 'react';
import {
    Text,
    View,
    StyleSheet,
    SectionList,
} from 'react-native';
import CardComponent from './CardComponent'

export default class Schedule extends Component {
    constructor(props) {
        super(props);
        this.state = {
          sectionData: [],
          loading: false,
        }
        this.contentOffsetY = 0;
        this._onScroll = this._onScroll.bind(this)
    }
    
    componentDidMount() {
        this.setState({ sectionData: this.props.data })
    }
    
    renderItem = ({item}) => (
        <CardComponent
            data={item}
            key={item}
        />
    );
    
    renderDateSeparator(text) {
        return (
            <Text style={{
                    paddingVertical: 15,
                    fontSize: 14,
                    flex: 1,
                    textAlign: 'center',
                    textAlignVertical: 'center',
                }}>
               {text}
            <Text>
        )
    }
    
    _onScroll(e){
        let contentOffset = e.nativeEvent.contentOffset.y;
        this.contentOffsetY < contentOffset ? this.loadMoreOnBottom() : this.loadMoreOnTop();
        this.contentOffsetY = contentOffset;
    }
    
    loadMoreOnTop() {
      this.setState({ lodaing: true });
      // code to append data on top of list
      this.setState({ lodaing: false });
    }
    
    loadMoreOnBottom() {
      // code to append data at bottom of list
    }
    
    render() {
      const sectionData = this.state.sectionData;
      return(
        <View style={{flex: 1}}>
          <SectionList
                onMomentumScrollEnd={this._onScroll}
                automaticallyAdjustContentInsets={false}
                itemShouldUpdate={false}
                renderItem={this.renderItem}
                renderSectionHeader={({section}) => this.renderDateSeparator(section.date)}
                sections={sectionData}
                stickySectionHeadersEnabled={false}
                refreshing={this.state.loading}
                onRefresh={() => this.loadMoreOnTop()}
                onEndReachedThreshold={0.3}
                onEndReached={() => this.loadMoreOnBottom()}
                keyExtractor={(item) => item.key}
            />
        </View>
      )
    }
}

提前致谢。

1 个答案:

答案 0 :(得分:1)

经过大量的研究,我终于在react-native中实现了双向无限滚动视图。

对于实现,我已将SectionList替换为FlatList,因为我想使用 scrollToOffset 方法,该方法在SectionList中无法正常工作。

我使用了javaScript的setInterval函数。它会定期检查列表需要从顶部或底部附加的天气。

这是我的代码:

&#13;
&#13;
import React, {Component} from 'react';
import {
    Text,
    View,
    StyleSheet,
    FlatList,
    Dimensions,
} from 'react-native';
import CardComponent from './CardComponent'

let {height, width} = Dimensions.get('window');

export default class Schedule extends Component {
    constructor(props) {
        super(props);
        this.state = {
          listData: [],
        }
        this.contentOffsetY = 0;
        this.pageOffsetY = 0;
        this.contentHeight = 0;
        
        this._onScroll = this._onScroll.bind(this);
        this.loadMoreOnTop = this.loadMoreOnTop.bind(this);
        this.loadMoreOnBottom = this.loadMoreOnBottom.bind(this);
    }
    
    componentDidMount() {
        this.setState({ listData: this.props.data });
        this._interval = setInterval(() => {
            this.setState({ load: true });
        }, 2000);
    }

    componentWillUnmount() {
        clearInterval(this._interval);
    }

    renderItem = ({item}) => (
        <CardComponent
            data={item}
            key={item}
        />
    );
    
    _onScroll(e){
        let contentOffset = e.nativeEvent.contentOffset.y;
        this.contentOffsetY < contentOffset ? this.loadMoreOnBottom() : this.loadMoreOnTop();
        this.contentOffsetY = contentOffset;
    }
        
    scrollToOffset = (offset) => {
        this.flatListRef ? this.flatListRef.scrollToOffset({animated: false, offset}) : null;
    };

    loadMoreOnTop() {
      let newOffset;
      
      // code to append data on top of list
      
      // calculate newOffset:
      newOffset = this.pageOffsetY + space required for new data.

      this.contentOffsetY = newOffset;
      this.scrollToOffset(newOffset);
    }
    
    loadMoreOnBottom() {
      // code to append data at bottom of list
    }
    
    render() {
      const listData = this.state.listData;
      
      if(this.pageOffsetY < 600) {
          this.loadMoreOnTop();
      } else if((this.contentHeight - this.pageOffsetY) < (height * 1.5)){
          this.loadMoreOnBottom();
      }
      return(
        <View style={{flex: 1}}>
          <FlatList
                onScroll={(e) => {
                    this.pageOffsetY = e.nativeEvent.contentOffset.y;
                    this.contentHeight = e.nativeEvent.contentSize.height;
                    return null;
                }}
                onMomentumScrollEnd={this._onScroll}
                automaticallyAdjustContentInsets={false}
                itemShouldUpdate={false}
                renderItem={this.renderItem}
                data={listData}
                refreshing={false}
                onRefresh={() => this.loadMoreOnTop()}
                onEndReachedThreshold={0.3}
                onEndReached={() => this.loadMoreOnBottom()}
                keyExtractor={(item) => item.key}
                ref={(ref) => { this.flatListRef = ref; }}
                animated={false}
            />
        </View>
      )
    }
}
&#13;
&#13;
&#13;