[iOS][Fabric] Pinch-zoomed ScrollView breaks (position jumps, cannot zoom back out) after its size changes
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 3/5
- Tempo estimado
- 1-2 dias
- Facilidade para iniciantes
- 25/100
- Tipo de issue
- Bug
- Clareza
- Claramente especificada
- Status de atividade
- Estagnada
- Stack de tecnologia
- ios, objective-c, react-native
- Domínio
- mobile
Direção de pesquisa
Comece com updateState:oldState: e prepareForRecycle de RCTScrollViewComponentView e, em seguida, execute o exemplo reproducer-react-native no iOS. Verifique o comportamento durante o zoom e ao redimensionar ou girar; está concluído quando a posição de rolagem permanece estável e o conteúdo pode voltar a ser totalmente reduzido após as alterações de tamanho.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Description
On iOS with the new architecture, a ScrollView with maximumZoomScale > 1 gets into a broken state whenever its size changes while the user is zoomed in (device rotation, or the layout around it changing):
- The scrolled position jumps to a different spot.
- The content can no longer be zoomed all the way back out; it stays stuck against one side or corner.
The only way to recover is to zoom all the way out in the broken state and then resize again (rotate back and forth). After that it works again until the next resize while zoomed.
Cause. RCTScrollViewComponentView returns _containerView from viewForZoomingInScrollView:, so while zoomed in that view carries UIScrollView's scale transform. In updateState:oldState: a content size change does
_containerView.frame = CGRect{RCTCGPointFromPoint(data.contentBoundingRect.origin), contentSize};
...
self->_scrollView.contentSize = contentSize;
- Setting
frameon a view whosetransformis not the identity is undefined behavior per the UIView docs ("If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored"). In practice UIKit shrinks the container'sboundsby the zoom scale, so when the user zooms back out to scale 1 the content is smaller than the scroll view and sits in a corner. contentSizeis set to the unzoomed size whilezoomScale != 1. UIScrollView itself keepscontentSizeat the zoomed size, so the offset is clamped to the wrong range and the position jumps.
The same code is on main today. prepareForRecycle already hints at it: "Invalidate cached content size so that updateState: recalculates the container frame after zoomScale reset (which may have mutated it in RTL)".
Fix: lay the container out through bounds/center and give the scroll view the zoomed content size. PR: https://github.com/react/react-native/pull/58498
Steps to reproduce
- Run the reproducer on an iOS device or simulator (new architecture is on by default).
- Pinch to zoom in (2x or more) and pan somewhere away from the top-left.
- Tap "Resize" (changes the ScrollView's height) or rotate the device.
- The position jumps. Pinch back out: the content stays stuck in a corner and does not fill the ScrollView.
- Zoom out fully, resize again: it recovers.
React Native Version
0.87.1
Affected Platforms
Runtime - iOS
Output of npx @react-native-community/cli info
Not run: the reproducer repository is a fresh `reproducer-react-native` template pinned to react-native 0.87.1, run on iOS 18 simulator/device.
Stacktrace or Logs
No crash or log output; the bug is visual.
MANDATORY Reproducer
https://github.com/mifi/reproducer-react-native
Screenshots and Videos
None yet.
- Linguagem predominante
- C++
- Estrelas
- 127k
- Forks
- 25.3k
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Tem um modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de react/react-native
-
Needs: Author Feedback Needs: Repro
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
react/react-native#58659 · 2 comentários ·
Mantenedores costumam responder em até 1 dia
-
Needs: Author Feedback Needs: Repro
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 92/100
react/react-native#58621 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
Needs: Attention Needs: Repro
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 85/100
react/react-native#58610 · 3 comentários ·
Mantenedores costumam responder em até 1 dia
-
Needs: Triage :mag:
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
react/react-native#58565 · 1 comentário · 2 reações ·
Mantenedores costumam responder em até 1 dia
-
Needs: Attention Needs: Repro
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 85/100
react/react-native#58526 · 2 comentários ·
Mantenedores costumam responder em até 1 dia
Todas as issues de react/react-native
Issues semelhantes
-
upstream update
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
conan-io/conan-center-index#31098 ·
Mantenedores costumam responder em até 2 dias
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 86/100
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
Mantenedores costumam responder em até 2 dias
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 85/100
ml-explore/mlx-c#136 ·
-
bug chart-audit
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 92/100
Mantenedores costumam responder em até 1 dia