代码之家  ›  专栏  ›  技术社区  ›  Morton

使用ListView时,如何知道哪个节头在顶部?

  •  0
  • Morton  · 技术社区  · 6 年前

    我想得到 y 每个节标题位于顶部时的位置值。

    例如, A、B、C 是我的标题,当a位于y值的顶部时 100 ,B是 500 ,C是 1200 .

    我的react本机项目版本是 0.44.2 ,因此我使用ListView来实现 SectionList .

    这是我的 ListView Facebook源代码:

    'use strict';
    
    var ListView = require('ListView');
    var Dimensions = require('Dimensions');
    var Platform = require('Platform');
    var StyleSheet = require('StyleSheet');
    var React = require('React');
    var View = require('View');
    
    type Rows = Array<Object>;
    type RowsAndSections = {
      [sectionID: string]: Object;
    };
    
    export type Data = Rows | RowsAndSections;
    type RenderElement = () => ?ReactElement;
    
    type Props = {
      data: Data;
      renderEmptyList?: ?RenderElement;
      minContentHeight: number;
      contentInset: { top: number; bottom: number; };
      contentOffset: { x: number; y: number; };
    };
    
    type State = {
      contentHeight: number;
      dataSource: ListView.DataSource;
    };
    
    // FIXME: Android has a bug when scrolling ListView the view insertions
    // will make it go reverse. Temporary fix - pre-render more rows
    const LIST_VIEW_PAGE_SIZE = Platform.OS === 'android' ? 20 : 1;
    
    class PureListView extends React.Component {
      props: Props;
      state: State;
    
      static defaultProps = {
        data: [],
        contentInset: { top: 0, bottom: 0 },
        contentOffset: { x: 0, y: 0 },
        // TODO: This has to be scrollview height + fake header
        minContentHeight: 0, //Dimensions.get('window').height,
        // renderSeparator: (sectionID, rowID) => <View style={styles.separator} key={rowID} />,
      };
    
      constructor(props: Props) {
        super(props);
        let dataSource = new ListView.DataSource({
          getRowData: (dataBlob, sid, rid) => dataBlob[sid][rid],
          getSectionHeaderData: (dataBlob, sid) => dataBlob[sid],
          rowHasChanged: (row1, row2) => row1 !== row2,
          sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
        });
    
        this.state = {
          contentHeight: 0,
          dataSource: cloneWithData(dataSource, props.data),
        };
    
        (this: any).renderFooter = this.renderFooter.bind(this);
        (this: any).onContentSizeChange = this.onContentSizeChange.bind(this);
      }
    
      componentWillReceiveProps(nextProps: Props) {
        if (this.props.data !== nextProps.data) {
          this.setState({
            dataSource: cloneWithData(this.state.dataSource, nextProps.data),
          });
        }
      }
    
      render() {
        const {contentInset} = this.props;
        const {contentOffset} = this.props;
        // console.log('ESDebug:content offset');
        // console.log(contentOffset);
        const bottom = contentInset.bottom +
          Math.max(0, this.props.minContentHeight - this.state.contentHeight);
        var removeSubviews = false;
        if (Platform.OS === 'android') {
          removeSubviews = true;
        }
        return (
          <ListView
            initialListSize={5}
            pageSize={LIST_VIEW_PAGE_SIZE}
            {...this.props}
            ref="listview"
            dataSource={this.state.dataSource}
            renderFooter={this.renderFooter}
            contentInset={{bottom, top: contentInset.top}}
            contentOffset={contentOffset}
            onContentSizeChange={this.onContentSizeChange}
            scrollEventThrottle={1000}
            decelerationRate ={'normal'}
            removeClippedSubviews={true}
          />
        );
      }
    
      onContentSizeChange(contentWidth: number, contentHeight: number) {
        if (contentHeight !== this.state.contentHeight) {
          this.setState({contentHeight});
        }
      }
    
      scrollTo(...args: Array<any>) {
        this.refs.listview.scrollTo(...args);
      }
    
      getScrollResponder(): any {
        return this.refs.listview.getScrollResponder();
      }
    
      renderFooter(): ?ReactElement {
        if (this.state.dataSource.getRowCount() === 0) {
          return this.props.renderEmptyList && this.props.renderEmptyList();
        }
    
        return this.props.renderFooter && this.props.renderFooter();
      }
    }
    
    function cloneWithData(dataSource: ListView.DataSource, data: ?Data) {
      if (!data) {
        return dataSource.cloneWithRows([]);
      }
      if (Array.isArray(data)) {
        return dataSource.cloneWithRows(data);
      }
      return dataSource.cloneWithRowsAndSections(data);
    }
    
    var styles = StyleSheet.create({
      separator: {
        backgroundColor: '#eeeeee',
        height: 1,
      },
    });
    
    module.exports = PureListView;
    

    这是我的组件代码 列表视图 :

        var PureListView = require('../../common/PureListView');
    
        render() {
          return (
                 <PureListView
                    ref={(pureListView) => { this.pureListView = pureListView; }}
                    style = {{marginTop:0, backgroundColor:'white'}}
                    contentContainerStyle = {{flexDirection: 'row',flexWrap: 'wrap'}}
                    data= {this.state.sectionData}
                    renderEmptyList={this.renderEmptyList}
                    renderSectionHeader={this._renderSectionHeader}
                    onScroll={this._onScroll}
                    renderRow={this._renderRow}
                    navigator={this.props.navigator}
                  />
          );
        }
    

    我从 _onScroll 函数,但我不知道当a或b或c标题位于顶部时如何获取y位置值。

    _onScroll(event) {
        let offset = event.nativeEvent.contentOffset;
        console.log(offset.y);  // y position value
      }
    

    任何帮助都将不胜感激。

    1 回复  |  直到 6 年前
        1
  •  1
  •   wijuwiju    6 年前

    您可以使用ONLAYOUT获取A、B和C初始Y位置,例如,在您的onscroll检查中,当滚动-A.Y的Y位置为0时,这将是顶部的当前标题。

    方法如下:

    https://facebook.github.io/react-native/docs/view#onlayout