OneScript

widget

小组件 API。

widget 提供小组件的配置值和显示能力。

触发以及执行逻辑

小组件会在两种情况下运行脚本:渲染小组件,以及用户编辑小组件时打开“选项”列表的配置阶段。两者都运行渲染脚本。OneScript 读取项目根目录 config.json 中的 entries.widget,决定运行 package.json 里的哪个脚本。可以在项目的“更多设置”中修改,也可以直接编辑该文件。

entries.widget 有两种写法:

  • 脚本名:渲染和点击使用同一个脚本。
  • 对象:render 和 click 分别指定脚本。

点击小组件暂不会运行脚本,click 目前不生效。

{
  "entries": {
    "widget": {
      "render": "widget:render",
      "click": "widget:click"
    }
  }
}

脚本名对应 package.json 中的 scripts:

{
  "scripts": {
    "widget:render": "src/widget-render.tsx",
    "widget:click": "src/widget-click.tsx"
  }
}

未配置渲染脚本时,依次使用 package.main、index.js、index.ts。配置的脚本不在 package.json 中,或对应文件不存在时,小组件会显示错误,不会回退。

import { widget } from "onescript"

widget.inputValue

用户在小组件配置中填写的输入值。

在主 App 预览中,该值为 undefined。在真实小组件中,该值来自小组件配置。

import { widget } from "onescript"

const inputValue = widget.inputValue

widget.option

用户在小组件“选项”列表中选中的候选项,未选择时为 undefined。候选项由配置阶段的 widget.provideOptions(options) 提供。

字段与脚本提供的候选项一致:id、title,以及可选的 subtitle、systemImage。用户把小组件切换到其他项目后,之前选中的选项属于原项目,不会传给脚本。

在主 App 预览中,该值为 undefined。

import { widget } from "onescript"

const city = widget.option?.id ?? "beijing"

widget.family

当前小组件的系统尺寸档位。

在真机小组件中,该值来自 WidgetKit 分配的 WidgetFamily。在主 App 预览中,该值与预览页选择的 Small / Medium / Large 一致。在编辑器或无运行时上下文中,默认值为 small。

可选值:small、medium、large、extraLarge。extraLarge 主要在 iPad 等大屏设备上出现,App 预览目前仅支持前三种。

import { widget } from "onescript"

const family = widget.family

widget.displaySize

当前小组件的 width 和 height,单位为 point。

import { widget } from "onescript"

const { width, height } = widget.displaySize

widget.show(options)

显示小组件视图。

仅在 app 和 widget 上下文中执行,调用后会自动终止脚本。在其他上下文中调用会被忽略。

import { widget } from "onescript"
import { Modifier, Text, VStack } from "onescript/views"

function renderWidget() {
  return (
    <VStack modifier={Modifier.padding(12)}>
      <Text>Hello Widget</Text>
    </VStack>
  )
}

await widget.show({
  views: renderWidget()
})

使用 widget.family 可以按尺寸档位返回不同视图。需要更细粒度的布局时,可配合 widget.displaySize。

import { widget } from "onescript"
import { Modifier, Text, VStack } from "onescript/views"

function renderWidget() {
  switch (widget.family) {
    case "small":
      return (
        <VStack modifier={Modifier.padding(12)}>
          <Text>紧凑</Text>
        </VStack>
      )
    case "medium":
      return (
        <VStack modifier={Modifier.padding(12)}>
          <Text>中等</Text>
        </VStack>
      )
    default:
      return (
        <VStack modifier={Modifier.padding(12)}>
          <Text>大</Text>
        </VStack>
      )
  }
}

await widget.show({
  views: renderWidget()
})

支持字段:

FieldDescription
views由 onescript/views 组件返回的视图。
options.refresh下一次请求刷新的最早时间,仅支持 Date。

省略 options.refresh 时,OneScript 默认在约一小时后请求刷新。refresh 表示系统最早可以刷新小组件的时间,不保证准点执行。

刷新时机由系统统一调度,并不保证准时触发。refresh 仅表示最早可刷新时间,实际更新可能晚于该时刻。

import { widget } from "onescript"
import { Modifier, Text, VStack } from "onescript/views"

const nextRefresh = new Date()
nextRefresh.setHours(8, 0, 0, 0)

if (nextRefresh <= new Date()) {
  nextRefresh.setDate(nextRefresh.getDate() + 1)
}

await widget.show({
  views: (
    <VStack modifier={Modifier.padding(12)}>
      <Text>早上好</Text>
    </VStack>
  ),
  options: {
    refresh: nextRefresh
  }
})

widget.provideOptions(options)

为系统“编辑小组件”面板中的“选项”列表提供候选项。

这个面板由 iOS 绘制,参数的名称和数量是固定的:项目、选项、输入值。用户打开“选项”列表时,OneScript 以 "widgetConfig" 上下文运行小组件的渲染脚本,并把脚本提供的候选项显示在列表中。用户选中后,渲染阶段通过 widget.option 读取。

仅在 widgetConfig 上下文中可用,在其他上下文中调用会抛出错误。调用后脚本结束。脚本没有调用它就结束时,“选项”列表为空。

字段说明
id必填。稳定的标识,在列表中不能重复。
title必填。面板中显示的文字。
subtitle可选。列表中显示在标题下方的次要文字。
systemImage可选。列表中显示在选项旁的 SF Symbol 名称。
import { script, widget } from "onescript"
import { Text } from "onescript/views"

if (script.context === "widgetConfig") {
  await widget.provideOptions([
    {
      id: "beijing",
      title: "北京",
      subtitle: "中国",
      systemImage: "building.2",
    },
    {
      id: "tokyo",
      title: "东京",
      subtitle: "日本",
    },
  ])
}

const city = widget.option?.title ?? "北京"

await widget.show({
  views: <Text>{city}</Text>
})

选中的选项由系统按小组件分别保存。主屏幕上的每个小组件各自保留自己的选择。

How is this guide?

最后更新于

本页目录