Home > other >  How to stay in position when new messages are loaded in a ScrollView in React-Native?
How to stay in position when new messages are loaded in a ScrollView in React-Native?

Time:05-27

I have a ScrollView containing messages (most recent messages are further) in a chat application.

I limit the number of pre-loaded messages, and I dynamically load a new batch when the Scroll View is scrolled to the top. So when new messages are loaded, the current scrollPos is at 0.

The problem is that when the new messages arrive, the scrollPos stays at 0, so the user is teleported to the oldest newly loaded message.

I have tried to deal with it by manually scrolling back down to the position using the size of the content change, but this is not satisfying as the user sees a back and forth scrolling.

Can someone think of a way to do this so that the user does not see any change when the new messages appear an can simply gradually scroll up to see them.

CodePudding user response:

I found a way to do it. The idea comes from the Invertible Scroll View component: https://github.com/expo/react-native-invertible-scroll-view

I didn't use the component but implemented the idea directly on the Scroll View to have minimal changes in my code.

To explain, we translate vertically the Scroll View using the style of the Scroll View and transform: [{ scaleY: -1 }]. We do the same for the children. Then, we revert the order of the messages.

In that setup, the scrollPos() measures from the visual bottom. To trigger the loading of the new messagges, now I use

const isCloseToBottom = ({layoutMeasurement, contentOffset, contentSize}) => {
  const paddingToBottom = 20;
  return layoutMeasurement.height   contentOffset.y >=
    contentSize.height - paddingToBottom;
};

The trick is that now, when the new messages appear on top, you have nothing to do as the distance from the user's point of view to the bottom does not change.

CodePudding user response:

You can use the onContentSizeChange prop to scroll to the bottom anytime it detects a change in content size.

The scrollToEnd function may differ depending on RN version.

<ScrollView
  ...
  onContentSizeChange={() => this.scrollView.scrollToEnd({animated: true})}>
</ScrollView>

Ref: https://reactnative.dev/docs/scrollview#scrolltoend

  • Related