Skip to content

fix: Android list jitter on prepend with maintainVisibleContentPosition - #536

Open
Critteros wants to merge 1 commit into
LegendApp:mainfrom
Critteros:fix/android-mvcp-anchor-subpixel-jitter
Open

fix: Android list jitter on prepend with maintainVisibleContentPosition#536
Critteros wants to merge 1 commit into
LegendApp:mainfrom
Critteros:fix/android-mvcp-anchor-subpixel-jitter

Conversation

@Critteros

Copy link
Copy Markdown

Fixes #535

Problem

On Android with maintainVisibleContentPosition, the list shifts by 1 to 2 px on
every prepend

Cause

The native MVCP helper anchors on the hidden ScrollAdjust view and scrolls by the
movement of that anchor. The anchor and the items rounded to the pixel grid differently:

  1. The anchor sits at top = bias + scrollAdjust with bias = 1e7. Yoga stores layout
    values as 32-bit floats. At 1e7 dp the float step is 1 dp, so the anchor could only
    move in whole dp and fractional adjust values were lost
  2. roundSize snapped item sizes to 1/8 dp. On a 3x screen that is a fractional number
    of physical pixels, so items moved by fractional pixel amounts

With 100.875 dp rows at scale 3, the anchor moved by 300 or 303 px while the items
moved by 302 or 303 px. The difference is the visible jitter

Fix

  1. bias is now 1e6. At 1e6 dp the float32 step is 0.0625 dp, which keeps the float
    error under half a physical pixel at all real densities. The anchor still sits after
    all real items until the content is more than 1e6 dp tall (about 10,000 mounted
    items at 100 dp each)
  2. roundSize now floors sizes to the physical pixel grid via PixelRatio.get()
    instead of 1/8 dp. Every adjust value is then a whole number of pixels, so a prepend
    moves the anchor and the items by the same number of pixels
  3. The web PixelRatio stub now reads window.devicePixelRatio

Both fixes are needed. With the bias change alone, the anchor and the items still
round to the pixel grid independently and each prepend leaves a 1 px shift

Measurements

30 s screen recordings under prepend traffic on a 480 dpi emulator (Pixel 9 Pro,
API 36, RN 0.83.6), comparing each frame with the previous one:

Build Frames with a shift
baseline 35, each 2 px
bias = 1e6 only 50, each 1 px
both fixes 0

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Android] list shifts by 1 to 2 px on every prepend with maintainVisibleContentPosition

1 participant