Skip to content

Platform metrics

A small process-wide store for values only the screen host can observe: safe-area insets, viewport size, and keyboard height. The host publishes them as the platform reports changes, and view handlers read them on demand instead of receiving them through every measurement call. Everything here is in layout units, points on iOS and density-independent pixels on Android, so the values add directly to other layout-unit values without conversion. Most app code reaches this indirectly, through use_safe_area_insets and use_window_dimensions.

Platform-level metrics shared between screen hosts and view handlers.

The screen host (pythonnative.screen) is the only place that knows about native window/safe-area state because it is the only piece of code that holds a reference to the native UIViewController (iOS) or Activity (Android). Native view handlers, however, need that state to size themselves correctly:

  • A bottom tab bar must claim both its visible 49 pt / 56 dp content height and the bottom safe-area inset so its background reaches the edge of the screen and the home indicator / gesture bar does not draw on top of the labels.
  • A future safe-area-aware container can read the same values instead of asking each native view for window metrics.

Rather than threading those values through every measure_intrinsic call signature, the screen host writes them here and handlers read them on demand. Values are in dp on Android and pt on iOS, i.e., the same "layout units" the layout engine uses on each platform, so handlers can add them to other layout-unit values without further conversion. On iOS the screen host consumes the top safe-area inset by positioning the root view below it, then publishes top=0 here; Android publishes the raw system-bar insets because the host view normally remains full-screen.

Example

from pythonnative.platform_metrics import ( ... get_safe_area_insets, set_safe_area_insets, ... ) set_safe_area_insets(top=44.0, left=0.0, bottom=34.0, right=0.0) get_safe_area_insets().bottom 34.0

Classes:

Name Description
SafeAreaInsets

Safe-area insets in layout units (pt on iOS, dp on Android).

WindowDimensions

Viewport size in layout units (pt on iOS, dp on Android).

Functions:

Name Description
subscribe

Register callback to fire whenever any metric changes.

set_safe_area_insets

Publish the current safe-area insets.

get_safe_area_insets

Return the current safe-area insets.

reset_safe_area_insets

Reset the insets back to (0, 0, 0, 0).

set_window_dimensions

Publish the viewport size in layout units.

get_window_dimensions

Return the current viewport size, or (0, 0) before first layout.

reset_window_dimensions

Reset window dimensions back to (0, 0). Intended for tests.

set_keyboard_height

Publish the on-screen keyboard height in layout units.

get_keyboard_height

Return the current on-screen keyboard height, or 0.0 if hidden.

reset_keyboard_height

Reset the keyboard height back to 0.0. Intended for tests.

ios_tab_bar_height

Return the iOS tab-bar intrinsic height in points.

Attributes:

Name Type Description
IOS_TAB_BAR_BASE_HEIGHT_PT float

UIKit HIG tab-bar content height in points.

IOS_TAB_BAR_BASE_HEIGHT_PT module-attribute

IOS_TAB_BAR_BASE_HEIGHT_PT: float = 49.0

UIKit HIG tab-bar content height in points.

The total bar reaches IOS_TAB_BAR_BASE_HEIGHT_PT + safe_area_insets.bottom so the pill background can extend over the home indicator. Apple's HIG places the tab bar flush with the screen edge and lets UIKit render its own internal padding for the home indicator.

SafeAreaInsets

Bases: NamedTuple

Safe-area insets in layout units (pt on iOS, dp on Android).

WindowDimensions

Bases: NamedTuple

Viewport size in layout units (pt on iOS, dp on Android).

subscribe

subscribe(
    callback: Callable[[], None],
) -> Callable[[], None]

Register callback to fire whenever any metric changes.

Returns an unsubscribe function. Hooks pass a state setter so a component re-renders whenever the platform reports a new value. Threadsafe: multiple subscribers may register/unregister concurrently.

set_safe_area_insets

set_safe_area_insets(
    top: float, left: float, bottom: float, right: float
) -> None

Publish the current safe-area insets.

Called by the platform-specific screen host whenever it learns a new value (e.g., on first layout, on rotation, on multitasking split-view changes). Negative inputs are clamped to 0.0 so handlers don't have to defend against bad data from native callers.

Parameters:

Name Type Description Default
top float

Distance in layout units from the top of the host container to the safe area (status bar / dynamic island / navigation bar).

required
left float

Inset from the left edge.

required
bottom float

Inset from the bottom edge (home indicator / gesture bar).

required
right float

Inset from the right edge.

required

get_safe_area_insets

get_safe_area_insets() -> SafeAreaInsets

Return the current safe-area insets.

The default value is (0, 0, 0, 0); handlers should still function correctly on a desktop / unit-test environment where no screen host has published insets.

reset_safe_area_insets

reset_safe_area_insets() -> None

Reset the insets back to (0, 0, 0, 0).

Intended for unit tests that need a clean slate between cases. Production code should use set_safe_area_insets instead.

set_window_dimensions

set_window_dimensions(width: float, height: float) -> None

Publish the viewport size in layout units.

Called by the screen host on initial layout, rotation, and split- view changes. Notifies subscribers (and therefore re-renders components using use_window_dimensions) only when the size actually changes.

get_window_dimensions

get_window_dimensions() -> WindowDimensions

Return the current viewport size, or (0, 0) before first layout.

reset_window_dimensions

reset_window_dimensions() -> None

Reset window dimensions back to (0, 0). Intended for tests.

set_keyboard_height

set_keyboard_height(height: float) -> None

Publish the on-screen keyboard height in layout units.

Negative inputs are clamped to 0.0. Notifies subscribers only when the value actually changes.

get_keyboard_height

get_keyboard_height() -> float

Return the current on-screen keyboard height, or 0.0 if hidden.

reset_keyboard_height

reset_keyboard_height() -> None

Reset the keyboard height back to 0.0. Intended for tests.

ios_tab_bar_height

ios_tab_bar_height() -> float

Return the iOS tab-bar intrinsic height in points.

Equal to IOS_TAB_BAR_BASE_HEIGHT_PT + safe_area_insets.bottom so the bar reaches the home indicator. The iOS screen host deliberately extends the root view past the bottom safe area for this very reason; the tab bar absorbs the inset and UIKit renders the pill with internal padding for the home indicator. Used by pythonnative.native_views.ios.TabBarHandler; exposed here so the formula is testable without importing the iOS handler module (which requires rubicon-objc).

Next steps

  • See the handlers that read these values in Native views.
  • See the ops that position a view once it's measured in Mutation ops.
  • See the other Python-side registry the native layer talks to in Events.
  • Use the hooks that wrap these in Hooks.