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 the Dimensions, PixelRatio, and Keyboard modules read them on demand. 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.hosts) 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 the backend's intrinsic measurement 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) plus its density.

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, 1, 1) before first layout.

reset_window_dimensions

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

set_screen_dimensions

Publish the physical screen size in layout units.

get_screen_dimensions

Return the physical screen size, or the window size before a host publishes one.

reset_screen_dimensions

Reset screen dimensions back to (0, 0, 1, 1). 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) plus its density.

Attributes:

Name Type Description
width float

Width in layout units.

height float

Height in layout units.

scale float

Physical pixels per layout unit (UIScreen.scale / DisplayMetrics.density / devicePixelRatio); 1.0 until the host reports it.

font_scale float

The user's text-size multiplier (Dynamic Type / fontScale); 1.0 until the host reports it.

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 in a 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,
    *,
    scale: Optional[float] = None,
    font_scale: Optional[float] = None
) -> 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 a value actually changes.

Parameters:

Name Type Description Default
width float

Viewport width in layout units.

required
height float

Viewport height in layout units.

required
scale Optional[float]

Pixels per layout unit. None keeps the current value (1.0 until a host reports one); 0 is treated as 1.0.

None
font_scale Optional[float]

Text-size multiplier. None keeps the current value; 0 is treated as 1.0.

None

get_window_dimensions

get_window_dimensions() -> WindowDimensions

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

reset_window_dimensions

reset_window_dimensions() -> None

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

set_screen_dimensions

set_screen_dimensions(
    width: float,
    height: float,
    *,
    scale: Optional[float] = None,
    font_scale: Optional[float] = None
) -> None

Publish the physical screen size in layout units.

The screen is the whole display (UIScreen.main.bounds / DisplayMetrics), as opposed to the window the app occupies in split view or with a keyboard showing. Hosts that can't tell the two apart publish the window size here. Notifies subscribers only when a value actually changes.

Parameters:

Name Type Description Default
width float

Screen width in layout units.

required
height float

Screen height in layout units.

required
scale Optional[float]

Pixels per layout unit; None keeps the current value.

None
font_scale Optional[float]

Text-size multiplier; None keeps the current value.

None

get_screen_dimensions

get_screen_dimensions() -> WindowDimensions

Return the physical screen size, or the window size before a host publishes one.

reset_screen_dimensions

reset_screen_dimensions() -> None

Reset screen dimensions back to (0, 0, 1, 1). 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. The Swift TabBarManager applies the same formula natively; this Python copy keeps the layout engine's expectations testable off device.

Next steps

  • See the backend that ships these values natively 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.