API

nsh/device

设备 API 向应用提供设备及其环境的信息。Rust 代码调用 nsh_core::ui::prelude 中的函数(window()、dark()、font_scale()、locale()、os()、idiom()、pixel_ratio()、set_color_scheme() 等);TSX 导入 nsh/device。窗口尺寸、配色方案、字体缩放、像素密度和区域设置是响应式的:在绑定(Rust 中传给元素的闭包,TSX 中的 JSX)、computed 或 effect 中读取它们,平台报告变化(旋转、窗口缩放、切换深色模式、修改文字大小或语言、移到另一种像素密度的屏幕)时,读取它们的地方会随之更新。

use nsh_core::{
    platform::{Appearance, Idiom, Os},
    ui::prelude::*, // window、dark、font_scale、locale、os、idiom、pixel_ratio、set_color_scheme……
};

教程见设备与环境。

#windowSize

const windowSize: Accessor<Size>;

界面的尺寸(点):窗口,或嵌入时的 NshAppView / NshView。响应式。Rust:window() -> Size<Points>。

let wide = move || window().width >= px(600.0);

view().style_when(wide, |s| s.flex_row())

#colorScheme

const colorScheme: Accessor<"light" | "dark">;

显示的外观:系统的外观,除非应用设置了自己的(nsh.json 的 "appearance"、setColorScheme)。响应式。Rust:dark() -> bool;主题颜色(AdaptiveColor)和 .dark(…) 样式变体无需读取它就会跟随。Tailwind 的 dark: 变体也跟随它(见 Tailwind)。

view().flex_1().bg(move || if dark() { black() } else { white() })

#fontScale

const fontScale: Accessor<number>;

用户偏好的文字大小相对于默认大小的比例(1 为默认;iOS 上是动态字体,Android 上是字体大小设置),或嵌入它的应用设置的文字大小。响应式。Rust:font_scale() -> f32。除非设置了 allowFontScaling={false},文本本身已经会随之缩放;当其他尺寸(例如文字旁边的图标)也需要跟随时再读取它。

#locale

const locale: Accessor<string>;

用户的区域设置,BCP 47 标签("en-US"、"zh-Hans-CN"),或嵌入它的应用设置的区域设置。响应式。Rust:locale() -> Locale(locale().as_str() 即标签)。Intl 默认按它格式化;读取它来选择你自己的翻译文案(设备与环境)。

#setColorScheme

function setColorScheme(scheme: "light" | "dark" | "system"): void;

无论系统外观如何,立即以 scheme 显示应用:colorScheme()、dark: 类、组件的主题和平台控件(警告框、状态栏的默认样式)都随之变化;"system" 重新跟随系统。nsh.json 的 "appearance" 从启动时就设置它。Rust:set_color_scheme(Appearance::Dark)(Appearance::Light、Appearance::System)。

#platform

const platform: Platform;

interface Platform {
  readonly os: "ios" | "android" | "macos" | "windows" | "linux" | "web";
  readonly version: string;
  readonly idiom: "phone" | "pad" | "mac" | "tv" | "desktop";
  readonly catalyst: boolean;
  select<T>(spec: PlatformSelectSpec<T>): T | undefined;
}

应用所运行的平台,运行期间不变。

成员Rust说明
osos() -> Os(os().name() 即 TS 的字符串)操作系统。iOS、iOS 模拟器和 Mac Catalyst 都报告 "ios",浏览器报告 "web"。
versionos_version() -> (u16, u16)iOS 和桌面系统:系统版本("17.5");Android:API 级别("35");Web:"0.0"。Rust 给出主版本和次版本号,在 Android 上是 API 级别和 0。
idiomidiom() -> Idiom;"desktop" 用 is_desktop()设备类型:"phone"、"pad"(iPad、Android 平板)、"mac"(以 Mac 形态运行的 Mac Catalyst)、"tv"(Apple TV、Android TV)或 "desktop",即适用桌面行为:macOS、Windows、Linux,以及有鼠标且窗口较宽的浏览器。
catalystidiom() == Idiom::Mac以 Mac 形态运行的 Mac Catalyst。
select(spec)match os() { … }当前平台对应的值(见下文)。
let columns = if is_desktop() { 3 } else { 1 };

#platform.select

interface PlatformSelectSpec<T> {
  ios?: T;
  android?: T;
  macos?: T;
  windows?: T;
  linux?: T;
  web?: T;
  mobile?: T;   // iOS、Android,以及手机和平板上的浏览器
  desktop?: T;  // macOS、Windows、Linux,以及桌面浏览器
  native?: T;   // 除 Web 外的所有平台
  default?: T;
}

依次返回当前操作系统(ios、android、web 等)对应的值,否则 mobile / desktop,否则 native(除 Web 外的所有平台),否则 default,都没有则返回 undefined。在浏览器中,mobile 还是 desktop 由设备类型决定。Rust 代码对 os() 做 match(mobile / desktop 用 is_desktop())。

use nsh_core::platform::Os;

let card = view().p_4();
let card = match os() {
    Os::Ios => card.shadow_color(black()).shadow_opacity(0.15).shadow_radius(px(8.0)),
    Os::Android => card.elevation(px(4.0)),
    _ => card,
};

#pixelRatio

const pixelRatio: Accessor<number>;

每个点对应的设备像素数(大多数 iPhone 上为 3)。响应式:窗口移动到另一种像素密度的屏幕上时(Mac Catalyst、桌面系统或外接显示器)它会变化。Rust:pixel_ratio() -> f32,取整到设备像素的长度用 round_to_nearest_pixel(points);在 TSX 中这个长度是 Math.round(x * pixelRatio()) / pixelRatio()。

let hairline = move || px(1.0 / pixel_ratio());

#布局方向

布局方向跟随用户的语言:在从右到左书写的语言(阿拉伯语、希伯来语等)中,应用从右到左布局,行从右侧开始排列,left / right 样式属性(marginLeft、paddingRight 等)表示起始端和结束端。修改即时生效,无需重启。

视图的 direction 样式("ltr"、"rtl" 或默认的 "inherit")设置其自身子树的方向;Rust 中为 .direction(LayoutDirection::..)。

view().direction(LayoutDirection::Rtl).flex_row().gap_2().child(text("First")).child(text("Second"))

#相关内容

  • 安全区域(Rust 的 safe_area();TSX 的 safeArea()、safeAreaInsets())和软键盘(Rust 的 keyboard_height();TSX 的 keyboardFrame())属于 nsh/base。
  • 屏幕阅读器和减弱动态效果的设置在 nsh/accessibility 中。