Lee
Lee

Reputation: 53

Flatlist visible position

I'm trying to render an curved vertical list like this iOS component: https://github.com/makotokw/CocoaWZYCircularTableView

That component (written in Obj-c) iterates the visible cells when laying them out, and sets the frame (i.e. indent) using asin.

I know in React Native I can set the leftMargin style in the renderItem callback, but I can't figure out how to get the on-screen index of the item - all I have is the index into the source data. And also, at that point, I don't think I have access to the absolute position.

Any ideas?

Upvotes: 2

Views: 5119

Answers (3)

Lee
Lee

Reputation: 53

Thanks for both answers.

What I have ended up doing is deriving the visible items using the scroll offset of the list. This is simple because the list items all have the same height.

I do this in the onScroll handler, and at that point I calculate the horizontal offset for each item (and I use leftMargin / rightMargin to render this). It's not perfect, but it does give me an elliptical list.

_handleScroll = (event) => {
  const topItemIndex = Math.floor(event.nativeEvent.contentOffset.y / LIST_ITEM_HEIGHT);
  const topItemSpare  = LIST_ITEM_HEIGHT-(event.nativeEvent.contentOffset.y % LIST_ITEM_HEIGHT);

  const positionFromEllipseTop = (forIndex-topItemIndex)*LIST_ITEM_HEIGHT+topItemSpare;
  const positionFromOrigin = Math.floor(Math.abs(yRadius - positionFromEllipseTop));

  const angle   = Math.asin(positionFromOrigin / yRadius);

  if (orientation === 'Left') {
    marginLeft  = 0;
    marginRight = ((xRadius * Math.cos(angle)))-LIST_ITEM_HEIGHT;
    alignSelf = 'flex-end';
  }
  else if (orientation === 'Right') {
    marginLeft  = (xRadius * Math.cos(angle))-LIST_ITEM_HEIGHT;
    marginRight = 0;
    alignSelf = 'flex-start';
  }
}

Upvotes: 2

Rajat Beck
Rajat Beck

Reputation: 1633

The function you are looking for is onViewableItemsChanged. You can use it with viewabilityConfig which provides us with minimumViewTime,viewAreaCoveragePercentThreshold,waitForInteraction which can be set accordingly

const VIEWABILITY_CONFIG = {
     minimumViewTime: 3000,
      viewAreaCoveragePercentThreshold: 100,
    waitForInteraction: true,
};


 _onViewableItemsChanged = (info: {
  changed: Array<{
    key: string,
    isViewable: boolean,
    item: any,
    index: ?number,
    section?: any,
     }>
    }
 ){
  //here you can have the index which is visible to you
  }

<FlatList
  renderItem={this.renderItem}
  data={this.state.data}
  onViewableItemsChanged={this._onViewableItemsChanged}
  viewabilityConfig={VIEWABILITY_CONFIG}
 />

Upvotes: 2

bennygenel
bennygenel

Reputation: 24660

React-native's FlatList component has a prop called onLayout. You can get the position of the component on screen with this prop.

onLayout

Invoked on mount and layout changes with:

{nativeEvent: { layout: {x, y, width, height}}}

This event is fired immediately once the layout has been calculated, but the new layout may not yet be reflected on the screen at the time the event is received, especially if a layout animation is in progress.

Upvotes: 1

Related Questions