| 2863 | // to the content top. Skip and let step 2 re-pick a valid anchor. |
| 2864 | if (anchorNode != nullptr && anchorNode->getYogaNode() != nullptr) { |
| 2865 | float newTop = preserveAnchorAbsoluteTop(this, anchorNode); |
| 2866 | float targetY = std::max(0.0f, std::min(newTop - scrollState.getPreserveAnchorScreenPos(), maxScroll)); |
| 2867 | float delta = targetY - offsetY; |
| 2868 | if (std::abs(delta) > 0.5f) { |
| 2869 | auto offset = scrollState.getDirectionAgnosticContentOffset(); |
| 2870 | offset.y = targetY; |
| 2871 | scrollState.updateDirectionAgnosticContentOffset(offset, offset); |
| 2872 | offsetY = targetY; |
| 2873 | updateResult.changed = true; |
| 2874 | scrollState.setNeedsSyncWithView(true); |
| 2875 | } |
| 2876 | } |
| 2877 | } |
| 2878 | |
| 2879 | // 2) Refresh the anchor to the node at the current viewport center. |
| 2880 | refreshPreserveAnchor(this, scrollState, offsetY, viewportH); |
| 2881 | } |
| 2882 | |
| 2883 | // Sticky headers: refresh per-child measurement cache from the current layout, then |
| 2884 | // reposition. Called on every layout pass to survive content-size changes (section |
| 2885 | // expand/collapse, rotation, keyboard, initial mount). |