Repository navigation
iOS: a layout pass during a page transition lays the page content out off screen #11568
Description
Issue Description
Runtime bug, iOS only.
If a page gets a layout pass while a navigation transition is running (for example, its content changes and requests a re-layout), its content is laid out off screen. The page turns into an empty rectangle with the Frame background showing through.
- No layout pass during the transition: nothing breaks.
- Frequent layout passes (for example, a counter updating several times per second): the page stays broken until the transition ends, then the first layout pass after it restores the page.
- A single layout pass during the transition: the page stays broken until something triggers another layout pass. In our app, the main screen stayed grey even after navigating back to it, until the next content update.
Cause. The transition animates the page's controller view with a transform. While that is applied, view.frame describes the moved rect (x = -W once the page has slid out). view.bounds is still 0, 0, W, H. Two places lay the page out from frame where they should use bounds:
Page.onLayoutlays out the content up toright - insets.right.rightcomes from the transformed frame, so the content width ends up wrong (0in the repro below).IOSHelper.getAvailableSpaceFromParentusesfullscreen = viewControllerView.frameand compares it with the safe area, which is inboundscoordinates. The content gets moved tox = -W.
Depending on the layout, the content ends up 0 wide or at x = -W, width = 1.5 * W. Either way it is off screen.
Expected behavior: a layout pass during a transition lays the page out the same way as one outside the transition.
Fix: draft PR #11517 fixes both places (bounds in getAvailableSpaceFromParent, and subtracting left/top in Page.onLayout). The PR was opened for a different trigger (edgesForExtendedLayout = Bottom) and has no linked issue. We applied its diff as a patch to @nativescript/core 9.1.3, and it fixes the repro below and our production app. Both hunks are needed: with only the getAvailableSpaceFromParent change, the content is no longer shifted but stays half as wide as the screen.
Not a regression: reproduced on @nativescript/core 9.0.10, 9.1.2 and 9.1.3, on iOS 18.6 and 26.3 simulators, and on an iOS 27 device.
Reproduction
app.css:
Frame {
background-color: #808080;
}
Page {
background-color: transparent;
}main-page.xml:
<Page actionBarHidden="true" navigatingFrom="onNavigatingFrom">
<GridLayout rows="*, auto" backgroundColor="#2e7d32">
<Label text="MAIN PAGE" horizontalAlignment="center" verticalAlignment="middle" />
<Button row="1" text="Open second page" tap="onOpen" />
</GridLayout>
</Page>main-page.ts:
import { EventData, Frame, NavigatedData, Page } from "@nativescript/core";
export function onNavigatingFrom(args: NavigatedData) {
const page = args.object as Page;
// Simulates a content update while the transition is running.
setTimeout(() => page.requestLayout(), 100);
}
export function onOpen(args: EventData) {
Frame.topmost().navigate({
moduleName: "second-page",
animated: true,
transition: { name: "slide" },
});
}second-page.xml can be any page.
ns run ios- Tap "Open second page".
- While it slides out, the green page turns grey (the
Framebackground), see the frames below.
In this minimal app the page is laid out again when you navigate back (viewDidLayoutSubviews on reappearing), so here the bug is only visible during the transition.
Without the fix:
With PR #11517 applied:
Relevant log output (if applicable)
# Repro above, iPhone 16 Pro simulator, iOS 26.3, W = 402. Logged right after the forced layout pass.
# core 9.1.3: broken on 5 of 5 navigations
content=0,0 0x874 page.frame=-402,0 402x874 page.bounds=0,0 402x874 transform tx=-402
# core 9.1.3 + PR #11517: 0 of 5
content=0,0 402x874 page.frame=-402,0 402x874 page.bounds=0,0 402x874 transform tx=-402
# Production app, iOS 27 device, W = 414, without the fix: the state it stays in
content=-414,0 621x896 page.frame=-414,0 414x896 page.bounds=0,0 414x896 transform tx=-414Environment
OS: macOS 15.7.3
CPU: (10) arm64 Apple M1 Pro
Shell: /bin/zsh
node: 26.12.0
npm: 11.20.0
nativescript: 9.1.1
# ios
xcode: 26.3/17C529
cocoapods: 1.16.2
ruby: 3.3.12
platforms:
- iOS 26.2"dependencies": {
"@nativescript/core": "9.1.3"
},
"devDependencies": {
"@nativescript/ios": "~9.1.0",
"@nativescript/types": "~9.1.0",
"@nativescript/webpack": "5.0.39",
"typescript": "~5.8.0"
}Please accept these terms
- I have searched the existing issues as well as StackOverflow and this has not been posted before
- This is a bug report
- I agree to follow this project's Code of Conduct
Activity