← 输入框|github.com|刷新
Skip to content

iOS: a layout pass during a page transition lays the page content out off screen #11568

Open

Description

@modos189

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:

  1. Page.onLayout lays out the content up to right - insets.right. right comes from the transformed frame, so the content width ends up wrong (0 in the repro below).
  2. IOSHelper.getAvailableSpaceFromParent uses fullscreen = viewControllerView.frame and compares it with the safe area, which is in bounds coordinates. The content gets moved to x = -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.

  1. ns run ios
  2. Tap "Open second page".
  3. While it slides out, the green page turns grey (the Frame background), 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:

Image

With PR #11517 applied:

Image

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=-414

Environment

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

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions