Как узнать, какой заголовок раздела находится сверху при использовании ListView? - PullRequest
0 голосов
/ 29 ноября 2018

Я хочу получить значение позиции y, когда каждый заголовок раздела находится сверху.

Например, A、B、C - это заголовок моего заголовка, когда A находится вверху, значение y равно 100, B - 500, C - 1200.

Моя собственная собственная версия проекта - 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;

А вот мой код компонентов о ListView:

    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}
              />
      );
    }

Я получаю значение позиции y из функции _onScroll, ноЯ понятия не имею, как получить значение позиции y, когда заголовок заголовка A или B или C. находится сверху.

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

Любая помощь будет оценена.

1 Ответ

0 голосов
/ 29 ноября 2018

Вы можете использовать onLayout для получения начальных y позиций A, B и C, например, при проверке onScroll, когда y позиция прокрутки - Ay равна 0, тогда это будет текущий верхний заголовок

метод:

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

...