Skip to content

Commit 13a72e0

Browse files
islandryufacebook-github-bot
authored andcommitted
Fix items disappear when zooming VirtualizedList (facebook#33765)
Summary: fix facebook#33705 Fixed the disappearance of items when scrolling after zooming VirtualizedList. example https://github.com/islandryu/zoomVirtualizedList Before modification https://user-images.githubusercontent.com/65934663/166849127-9fc3ba84-5172-4ae1-bd44-dd6312f283ec.mov After modification https://user-images.githubusercontent.com/65934663/166868632-2f78e118-f705-442d-b94e-ff165bed26c7.mov ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> [General] [Fixed] - Fixed the disappearance of items when scrolling after zooming VirtualizedList. Pull Request resolved: facebook#33765 Test Plan: Make the VirtualizedList zoomable with a prop such as maximumZoomScale. Apply the patch and make sure that items in the VirtualizedList do not disappear when you scroll after zooming the VirtualizedList. Or apply the patch from this repository and check it. https://github.com/islandryu/zoomVirtualizedList Reviewed By: javache Differential Revision: D36169686 Pulled By: yungsters fbshipit-source-id: 0f86255c2864be13f6d2dc5a58af1d11c9eedac3
1 parent 9328115 commit 13a72e0

File tree

5 files changed

+26
-13
lines changed

5 files changed

+26
-13
lines changed

Libraries/Lists/VirtualizeUtils.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ export function elementsThatOverlapOffsets(
2525
offset: number,
2626
...
2727
},
28+
zoomScale: number,
2829
): Array<number> {
2930
const out = [];
3031
let outLength = 0;
3132
for (let ii = 0; ii < itemCount; ii++) {
3233
const frame = getFrameMetrics(ii);
33-
const trailingOffset = frame.offset + frame.length;
34+
const trailingOffset = (frame.offset + frame.length) * zoomScale;
3435
for (let kk = 0; kk < offsets.length; kk++) {
3536
if (out[kk] == null && trailingOffset >= offsets[kk]) {
3637
out[kk] = ii;
@@ -104,6 +105,7 @@ export function computeWindowedRenderLimits(
104105
offset: number,
105106
velocity: number,
106107
visibleLength: number,
108+
zoomScale: number,
107109
...
108110
},
109111
): {
@@ -115,7 +117,7 @@ export function computeWindowedRenderLimits(
115117
if (itemCount === 0) {
116118
return prev;
117119
}
118-
const {offset, velocity, visibleLength} = scrollMetrics;
120+
const {offset, velocity, visibleLength, zoomScale} = scrollMetrics;
119121

120122
// Start with visible area, then compute maximum overscan region by expanding from there, biased
121123
// in the direction of scroll. Total overscan area is capped, which should cap memory consumption
@@ -136,7 +138,8 @@ export function computeWindowedRenderLimits(
136138
);
137139
const overscanEnd = Math.max(0, visibleEnd + leadFactor * overscanLength);
138140

139-
const lastItemOffset = getFrameMetricsApprox(itemCount - 1).offset;
141+
const lastItemOffset =
142+
getFrameMetricsApprox(itemCount - 1).offset * zoomScale;
140143
if (lastItemOffset < overscanBegin) {
141144
// Entire list is before our overscan window
142145
return {
@@ -150,6 +153,7 @@ export function computeWindowedRenderLimits(
150153
[overscanBegin, visibleBegin, visibleEnd, overscanEnd],
151154
itemCount,
152155
getFrameMetricsApprox,
156+
zoomScale,
153157
);
154158
overscanFirst = overscanFirst == null ? 0 : overscanFirst;
155159
first = first == null ? Math.max(0, overscanFirst) : first;

Libraries/Lists/VirtualizedList.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
12281228
timestamp: 0,
12291229
velocity: 0,
12301230
visibleLength: 0,
1231+
zoomScale: 1,
12311232
};
12321233
_scrollRef: ?React.ElementRef<any> = null;
12331234
_sentEndForContentLength = 0;
@@ -1624,6 +1625,9 @@ class VirtualizedList extends React.PureComponent<Props, State> {
16241625
);
16251626
this._hasWarned.perf = true;
16261627
}
1628+
1629+
const zoomScale = e.nativeEvent.zoomScale;
1630+
16271631
this._scrollMetrics = {
16281632
contentLength,
16291633
dt,
@@ -1632,6 +1636,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
16321636
timestamp,
16331637
velocity,
16341638
visibleLength,
1639+
zoomScale,
16351640
};
16361641
this._updateViewableItems(this.props.data);
16371642
if (!this.props) {

Libraries/Lists/VirtualizedListContext.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Context = $ReadOnly<{
4747
timestamp: number,
4848
velocity: number,
4949
visibleLength: number,
50+
zoomScale: number,
5051
},
5152
horizontal: ?boolean,
5253
getOutermostParentListRef: () => VirtualizedList,

Libraries/Lists/__tests__/VirtualizeUtils-test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ describe('elementsThatOverlapOffsets', function () {
4848
offset: 100 * index,
4949
};
5050
}
51-
expect(elementsThatOverlapOffsets(offsets, 100, getFrameMetrics)).toEqual([
52-
0, 2, 3, 4,
53-
]);
51+
expect(
52+
elementsThatOverlapOffsets(offsets, 100, getFrameMetrics, 1),
53+
).toEqual([0, 2, 3, 4]);
5454
});
5555
it('handles variable length', function () {
5656
const offsets = [150, 250, 900];
@@ -62,7 +62,7 @@ describe('elementsThatOverlapOffsets', function () {
6262
{offset: 950, length: 150},
6363
];
6464
expect(
65-
elementsThatOverlapOffsets(offsets, frames.length, ii => frames[ii]),
65+
elementsThatOverlapOffsets(offsets, frames.length, ii => frames[ii], 1),
6666
).toEqual([1, 1, 3]);
6767
});
6868
it('handles out of bounds', function () {
@@ -73,7 +73,7 @@ describe('elementsThatOverlapOffsets', function () {
7373
{offset: 250, length: 100},
7474
];
7575
expect(
76-
elementsThatOverlapOffsets(offsets, frames.length, ii => frames[ii]),
76+
elementsThatOverlapOffsets(offsets, frames.length, ii => frames[ii], 1),
7777
).toEqual([1]);
7878
});
7979
it('errors on non-increasing offsets', function () {
@@ -84,7 +84,7 @@ describe('elementsThatOverlapOffsets', function () {
8484
{offset: 250, length: 100},
8585
];
8686
expect(() => {
87-
elementsThatOverlapOffsets(offsets, frames.length, ii => frames[ii]);
87+
elementsThatOverlapOffsets(offsets, frames.length, ii => frames[ii], 1);
8888
}).toThrowErrorMatchingSnapshot();
8989
});
9090
});

Libraries/Lists/__tests__/VirtualizedList-test.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ describe('VirtualizedList', () => {
384384

385385
const instance = component.getInstance();
386386

387-
instance._onLayout({nativeEvent: {layout}});
387+
instance._onLayout({nativeEvent: {layout, zoomScale: 1}});
388388

389389
const initialContentHeight = props.initialNumToRender * ITEM_HEIGHT;
390390

@@ -1490,7 +1490,7 @@ it('calls _onCellLayout properly', () => {
14901490
);
14911491
const cell = virtualList._cellRefs.i4;
14921492
const event = {
1493-
nativeEvent: {layout: {x: 0, y: 0, width: 50, height: 50}},
1493+
nativeEvent: {layout: {x: 0, y: 0, width: 50, height: 50}, zoomScale: 1},
14941494
};
14951495
cell._onLayout(event);
14961496
expect(mock).toHaveBeenCalledWith(event, 'i4', 3);
@@ -1544,7 +1544,9 @@ function simulateLayout(component, args) {
15441544

15451545
function simulateViewportLayout(component, dimensions) {
15461546
lastViewportLayout = dimensions;
1547-
component.getInstance()._onLayout({nativeEvent: {layout: dimensions}});
1547+
component
1548+
.getInstance()
1549+
._onLayout({nativeEvent: {layout: dimensions}, zoomScale: 1});
15481550
}
15491551

15501552
function simulateContentLayout(component, dimensions) {
@@ -1558,7 +1560,7 @@ function simulateCellLayout(component, items, itemIndex, dimensions) {
15581560
const instance = component.getInstance();
15591561
const cellKey = instance._keyExtractor(items[itemIndex], itemIndex);
15601562
instance._onCellLayout(
1561-
{nativeEvent: {layout: dimensions}},
1563+
{nativeEvent: {layout: dimensions, zoomScale: 1}},
15621564
cellKey,
15631565
itemIndex,
15641566
);
@@ -1570,6 +1572,7 @@ function simulateScroll(component, position) {
15701572
contentOffset: position,
15711573
contentSize: lastContentLayout,
15721574
layoutMeasurement: lastViewportLayout,
1575+
zoomScale: 1,
15731576
},
15741577
});
15751578
}

0 commit comments

Comments
 (0)