From c281788f6bf84de7797608f77314071ea8fc00ee Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 15 Jul 2022 16:17:39 +0800 Subject: [PATCH] draft - when items are appended to the end of the list, the view needs to stay in the same position it works when _onScroll is triggered: - the user scroll the list - the bottomY state is updated - appending item to the list will not change position still does not work when the user appends a second item Related https://github.com/facebook/react-native/issues/30373#issuecomment-1185178383 Was implemented on a Javascript example above, which had similar issues - did not work if no scroll was triggered - did not work if triggering many times fast appends of items Reason for this issues needs to be investigated, but the solution only be for TalkBack users to avoid using transform --- Libraries/Lists/VirtualizedList.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index ba3966dbdae899..5630a5c527c87a 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -724,6 +724,9 @@ class VirtualizedList extends React.PureComponent { (this.props.initialScrollIndex || 0) + initialNumToRenderOrDefault(this.props.initialNumToRender), ) - 1, + height: undefined, + resetScrollPosition: false, + bottomHeight: 0, }; if (this._isNestedWithSameOrientation()) { @@ -1007,6 +1010,14 @@ class VirtualizedList extends React.PureComponent { firstAfterInitial, last, ); + const {resetScrollPosition, height, bottomHeight} = this.state; + if (resetScrollPosition && bottomHeight) { + this.scrollToOffset({ + offset: height - bottomHeight, + animated: false, + }); + this.setState({resetScrollPosition: false}); + } // scroll to bottom optimization. The last page is always rendered in an inverted flatlist. if (this.props.inverted) { this._pushCells( @@ -1174,6 +1185,13 @@ class VirtualizedList extends React.PureComponent { componentDidUpdate(prevProps: Props) { const {data, extraData} = this.props; + const dataAppended = + data[data.length - 1] != prevProps.data[prevProps.data.length - 1]; + const dataPrepended = data[0] != prevProps.data[0]; + if (dataAppended) { + this.setState({bottomHeight: this.bottomY}); + } + if (data !== prevProps.data || extraData !== prevProps.extraData) { // clear the viewableIndices cache to also trigger // the onViewableItemsChanged callback with the new data @@ -1592,6 +1610,7 @@ class VirtualizedList extends React.PureComponent { } this._scheduleCellsToRenderUpdate(); this._maybeCallOnEndReached(); + this.setState({height: height, resetScrollPosition: true}); }; /* Translates metrics from a scroll event in a parent VirtualizedList into @@ -1629,6 +1648,9 @@ class VirtualizedList extends React.PureComponent { let contentLength = this._selectLength(e.nativeEvent.contentSize); let offset = this._selectOffset(e.nativeEvent.contentOffset); let dOffset = offset - this._scrollMetrics.offset; + const scrollY = e.nativeEvent.contentOffset.y; + const height = e.nativeEvent.contentSize.height; + this.bottomY = height - scrollY; if (this._isNestedWithSameOrientation()) { if (this._scrollMetrics.contentLength === 0) {