Как получить текущий видимый индекс в плоском списке RN

У меня есть горизонтальный плоский список, где каждый элемент имеет width:300 Все, что я пытаюсь сделать, это получить индекс видимого в данный момент элемента.

<FlatList 
            onScroll={(e) => this.handleScroll(e)} 
            horizontal={true}
            data={this.state.data}
            renderItem...

Пробовал это:

handleScroll(event) {
    let index = Math.ceil(
      event.nativeEvent.contentOffset.x / 300
    );

И что-то вроде этого:

handleScroll(event) {
  let contentOffset = event.nativeEvent.contentOffset;
  let index = Math.floor(contentOffset.x / 300);

но ничего точно, я всегда получаю один индекс вверх или один индекс вниз.
Что я делаю неправильно и как получить правильный текущий индекс в плоском списке?

Например, я получаю элемент списка, который является восьмым в списке, но я получаю индекс 9 или 10.
enter image description here

Ответ 1

UPD. спасибо fzyzcjy за указание, что onViewableItemsChanged не должен обновляться

Вы можете использовать FlatList onViewableItemsChanged prop, чтобы получить то, что вы хотите.

class Test extends React.Component {
  onViewableItemsChanged = ({ viewableItems, changed }) => {
    console.log("Visible items are", viewableItems);
    console.log("Changed in this iteration", changed);
  }

  render () => {
    return (
      <FlatList
        onViewableItemsChanged={this.onViewableItemsChanged }
        viewabilityConfig={{
          itemVisiblePercentThreshold: 50
        }}
      />
    )
  }
}

viewabilityConfig может помочь вам сделать все, что вы хотите с настройками видимости. В примере кода 50 означает, что элемент считается видимым, если он виден более чем на 50 процентов.

Конфигурацию конфигурации можно найти здесь

Ответ 2

Большое спасибо за самый проголосовавший ответ :) Однако, когда я его пробую, он не работает, что выдает ошибку о том, что changing onViewableItemsChanged on the fly is not supported. После некоторого поиска я нашел решение здесь. Вот полный код, который может работать без ошибок. Ключевым моментом является то, что эти две конфигурации должны быть указаны как свойства класса, а не внутри функции render().

class MyComponent extends Component {  
  _onViewableItemsChanged = ({ viewableItems, changed }) => {
    console.log("Visible items are", viewableItems);
    console.log("Changed in this iteration", changed);
  };

  _viewabilityConfig = {
    itemVisiblePercentThreshold: 50
  };

  render() {
    return (
        <FlatList
          onViewableItemsChanged={this._onViewableItemsChanged}
          viewabilityConfig={this._viewabilityConfig}
          {...this.props}
        />
      </View>
    );
  }
}

Ответ 3

this.handleScroll = (event) => {
  let yOffset = event.nativeEvent.contentOffset.y
  let contentHeight = event.nativeEvent.contentSize.height
  let value = yOffset / contentHeight
}

<FlatList onScroll={this.handleScroll} />

Получите значение округления для расчета номера страницы/индекса.

Ответ 4

С ответами, связанными с @fzyzcjy и @Roman. В ответ 16. 8+ вы можете использовать uscCallback для обработки ошибки changing onViewableItemsChanged on the fly is not supported.

function MyComponent(props) {
    const _onViewableItemsChanged = useCallback(({ viewableItems, changed }) => {
        console.log("Visible items are", viewableItems);
        console.log("Changed in this iteration", changed);
    }, []);

    const _viewabilityConfig = {
        itemVisiblePercentThreshold: 50
    }

    return <FlatList
            onViewableItemsChanged={_onViewableItemsChanged}
            viewabilityConfig={_viewabilityConfig}
            {...props}
        />;
}