Skip to content

Commit

Permalink
Right align scrollToIndex in RTL (#38737)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #38737

This fixes up behavior on Android so that `scrollToIndex` aligns the right edge of the cell of the given index to the right edge of the scrollview viewport. We do not incorporate RTL on iOS which inverts x/y coordinates from scroller (but not layout).

Changelog:
[General][Fixed] - Right align scrollToIndex in RTL

Reviewed By: lenaic

Differential Revision: D47978637

fbshipit-source-id: c4a37e5864f80f1750c394f9ce8a47db735a49a8
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Aug 4, 2023
1 parent eb41627 commit 0949fa6
Showing 1 changed file with 35 additions and 35 deletions.
70 changes: 35 additions & 35 deletions packages/virtualized-lists/Lists/VirtualizedList.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,23 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {

scrollRef.scrollTo({
animated,
...this._cartesianScrollOffset(offset),
...this._scrollToParamsFromOffset(offset),
});
}

_scrollToParamsFromOffset(offset: number): {x?: number, y?: number} {
const {horizontal, rtl} = this._orientation();
if (horizontal && rtl) {
// Add the visible length of the scrollview so that the offset is right-aligned
const cartOffset = this._listMetrics.cartesianOffset(
offset + this._scrollMetrics.visibleLength,
);
return horizontal ? {x: cartOffset} : {y: cartOffset};
} else {
return horizontal ? {x: offset} : {y: offset};
}
}

recordInteraction() {
this._nestedChildLists.forEach(childList => {
childList.recordInteraction();
Expand Down Expand Up @@ -1480,39 +1493,6 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
: metrics.width;
}

_flowRelativeScrollOffset(
metrics: $ReadOnly<{
x: number,
y: number,
...
}>,
contentSize: $ReadOnly<{
width: number,
height: number,
...
}>,
): number {
let offset = this._selectOffset(metrics);

const {horizontal, rtl} = this._orientation();
if (horizontal && rtl && Platform.OS !== 'ios') {
offset = this._selectLength(contentSize) - offset;
}

return offset;
}

_cartesianScrollOffset(offset: number): {x?: number, y?: number} {
const {horizontal, rtl} = this._orientation();
const normalizedOffset =
horizontal && rtl && Platform.OS !== 'ios'
? this._listMetrics.getContentLength() - offset
: offset;

const cartOffset = this._listMetrics.cartesianOffset(normalizedOffset);
return horizontal ? {x: cartOffset} : {y: cartOffset};
}

_selectOffset({x, y}: $ReadOnly<{x: number, y: number, ...}>): number {
return this._orientation().horizontal ? x : y;
}
Expand Down Expand Up @@ -1688,7 +1668,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
const timestamp = e.timeStamp;
let visibleLength = this._selectLength(e.nativeEvent.layoutMeasurement);
let contentLength = this._selectLength(e.nativeEvent.contentSize);
let offset = this._flowRelativeScrollOffset(
let offset = this._offsetFromScrollEvent(
e.nativeEvent.contentOffset,
e.nativeEvent.contentSize,
);
Expand Down Expand Up @@ -1755,6 +1735,26 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
this._scheduleCellsToRenderUpdate();
};

_offsetFromScrollEvent(
contentOffset: $ReadOnly<{
x: number,
y: number,
...
}>,
contentSize: $ReadOnly<{
width: number,
height: number,
...
}>,
): number {
const {horizontal, rtl} = this._orientation();
if (Platform.OS === 'ios' || !(horizontal && rtl)) {
return this._selectOffset(contentOffset);
}

return this._selectLength(contentSize) - this._selectOffset(contentOffset);
}

_scheduleCellsToRenderUpdate(opts?: {allowImmediateExecution?: boolean}) {
const allowImmediateExecution = opts?.allowImmediateExecution ?? true;

Expand Down

0 comments on commit 0949fa6

Please sign in to comment.