首页
/ Electron TouchBarSpacer 指南:用 `size` 参数精准控制 macOS 触控栏间距布局

Electron TouchBarSpacer 指南:用 `size` 参数精准控制 macOS 触控栏间距布局

2026-09-06 18:07:32作者:郦嵘贵Just

TouchBarSpacer 是 Electron 面向 macOS 原生 Touch Bar(触控栏)提供的布局辅助类,用于在 TouchBar 的各个条目(如按钮、标签、滑块)之间插入一段视觉间隔。本文围绕它在当前仓库中的完整 API 定义展开,结合 JS 层实现与原生 Objective-C++ 映射源码,说明 smalllargeflexible 三种取值各自的含义与底层行为,并给出可直接运行的组合示例,帮助你构建间距整洁、分组清晰的触控栏界面。

TouchBarSpacer 是什么

TouchBarSpacer 用于在原生 macOS 应用(即 macOS 上运行的 Electron 应用)的 Touch Bar 中,在两个条目之间创建一个间隔区域。它对应官方文档的类描述:

Create a spacer between two items in the touch bar for native macOS applications

其本质是对 AppKit 中 NSTouchBar 固定/弹性间隔标识符的一层封装:Electron 通过它将你传入的 size 字符串翻译为原生的 NSTouchBarItemIdentifierFixedSpaceSmallNSTouchBarItemIdentifierFixedSpaceLargeNSTouchBarItemIdentifierFlexibleSpace

使用限制如下:

  • 仅在主进程(Main Process)可用:参考 术语表 Main Process 说明
  • 不能从 'electron' 模块顶层直接导入:官方文档明确指出 This class is not exported from the 'electron' module. It is only available as a return value of other methods in the Electron API。实践中通过 TouchBar 类的静态属性取用(见下文);
  • Touch Bar 相关 API 整体仍处于实验阶段(Electron 官方在 docs/api/touch-bar.md 中标注 "experimental and may change or be removed in future Electron releases");
  • 仅适用于配备 Touch Bar 的 macOS 设备;无 Touch Bar 时该界面不显示。

构造语法与参数说明

new TouchBarSpacer(options)

  • options Object
    • size string (optional) — 间隔大小,取值范围如下:
size 取值 视觉效果 对应的原生标识符 说明
small 固定小间隔 NSTouchBarItemIdentifierFixedSpaceSmall 默认值,不传 size 时采用此值
large 固定大间隔 NSTouchBarItemIdentifierFixedSpaceLarge 视觉上明显大于 small
flexible 弹性间隔 NSTouchBarItemIdentifierFlexibleSpace 占据两个相邻条目之间的全部剩余可用空间

TypeScript 层实现 lib/browser/api/touch-bar.ts 中,TouchBarSpacer 的定义为:

class TouchBarSpacer
  extends TouchBarItem<Electron.TouchBarSpacerConstructorOptions>
  implements Electron.TouchBarSpacer
{
  @ImmutableProperty(() => 'spacer')
  type!: string;

  @ImmutableProperty<TouchBarSpacer>((config) => config.size)
  size!: Electron.TouchBarSpacer['size'];

  onInteraction = null;
}

从这段源码可以确认两个关键实现事实:

  1. size 是只读不可变属性:它使用 @ImmutableProperty 装饰器在构造时从 config.size 一次性固化,对应的属性访问器没有 set 方法,运行期赋值会抛出 Cannot override property 错误。也就是说,你需要在构造时决定间距类型,无法像 TouchBarLabel.label 那样运行时动态修改。
  2. 间隔没有交互行为onInteraction 恒为 null,与按钮、滑块等可交互条目的区分点就在这里。

实例属性 touchBarSpacer.size

每个 TouchBarSpacer 实例暴露一个只读字符串属性 size,取值为 smalllargeflexible,即构造时传入并在实例上固化的值。

如何获取 TouchBarSpacer 类

由于 TouchBarSpacer 不从 'electron' 模块顶层导出,需要借助 TouchBar 类的静态属性获取。Electron 在主文档 docs/api/touch-bar.md 中为每种条目都声明了同名静态引用:

const { TouchBar } = require('electron')

// 从 TouchBar 的静态属性解构出各个条目类
const { TouchBarButton, TouchBarLabel, TouchBarSpacer } = TouchBar

const spacer = new TouchBarSpacer({ size: 'large' })

这正对应源码中 TouchBar 类末尾的静态挂载:static TouchBarSpacer = TouchBarSpacer;(见 lib/browser/api/touch-bar.ts)。使用 ES Module 语法时同理:const { TouchBarSpacer } = TouchBar; 或直接 new TouchBar.TouchBarSpacer(...)

size 三种取值与原生层映射原理

了解每种取值的真实行为,最直接的方式是追踪 Electron 原生侧的映射逻辑。负责把 JS 配置转成 NSTouchBar 条目的代码位于 shell/browser/ui/cocoa/electron_touch_bar.mm

if (type == "spacer") {
  std::string size;
  item.Get("size", &size);
  if (size == "large") {
    identifier = NSTouchBarItemIdentifierFixedSpaceLarge;
  } else if (size == "flexible") {
    identifier = NSTouchBarItemIdentifierFlexibleSpace;
  } else {
    identifier = NSTouchBarItemIdentifierFixedSpaceSmall;
  }
}

small(默认值)

对应 NSTouchBarItemIdentifierFixedSpaceSmall。在原生的 defaultItemIdentifiers 数组中,它是一个宽度固定的「小空隙」标识符,适合给紧密相邻的同组控件留出轻微呼吸感。由于映射逻辑把「非 large、非 flexible」的一切情况都归入 small,因此构造时省略 size、传 undefined、甚至传入无法识别的字符串,最终都会安全退化为 small

large

对应 NSTouchBarItemIdentifierFixedSpaceLarge,是固定宽度的大空隙。适合用于把语义不同的条目分组:例如把「操作类按钮」和「状态类标签」在视觉上拉开,避免误读为同一组。老虎机示例中即用它把 Spin 按钮与结果标签隔开。

flexible

对应 NSTouchBarItemIdentifierFlexibleSpace。AppKit 会把所有 flexible 标识符在栏内剩余的可用空间中按比例分配,实现经典的两端对齐或居中布局:

  • 间隔前放一个 flexible 间隔、间隔后紧接一组按钮,就能把按钮「推」到 Touch Bar 右侧;
  • 在左右各放一个 flexible、中间放一个标签,则标签在栏内水平居中。

需要特别留意:flexible 的真正生效依赖整条栏的剩余空间。若整条 Touch Bar 的条目总宽度恰好占满,弹性间隔的可视宽度会趋近于零,此时它与 small/large 的视觉差异并不明显。

完整可运行示例:在老虎机布局中插入间隔

官方在 docs/api/touch-bar.md 给出的「老虎机 Touch Bar 小游戏」示范了 spacer 的真实用途——把按钮、三个滚轮标签与结果标签组织成层次分明的布局。其布局核心部分如下:

const { app, BrowserWindow, TouchBar } = require('electron')

const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar

// 三个滚轮标签与结果标签
const reel1 = new TouchBarLabel({ label: '' })
const reel2 = new TouchBarLabel({ label: '' })
const reel3 = new TouchBarLabel({ label: '' })
const result = new TouchBarLabel({ label: '' })

// Spin 按钮(此处省略 click 回调中的抽奖逻辑)
const spin = new TouchBarButton({
  label: '🎰 Spin',
  backgroundColor: '#7851A9',
  click: () => { /* ... */ }
})

// 用 large / small spacer 对条目分组
const touchBar = new TouchBar({
  items: [
    spin,
    new TouchBarSpacer({ size: 'large' }),  // 按钮组与滚轮组之间的大间隔
    reel1,
    new TouchBarSpacer({ size: 'small' }),  // 滚轮之间的紧凑间隔
    reel2,
    new TouchBarSpacer({ size: 'small' }),
    reel3,
    new TouchBarSpacer({ size: 'large' }),  // 滚轮组与结果标签之间的大间隔
    result
  ]
})

let window

app.whenReady().then(() => {
  window = new BrowserWindow({
    frame: false,
    titleBarStyle: 'hiddenInset',
    width: 200,
    height: 200,
    backgroundColor: '#000'
  })
  window.loadURL('about:blank')
  window.setTouchBar(touchBar)   // 通过 BrowserWindow.setTouchBar 挂载到窗口
})

运行步骤:

  1. 将上述代码保存为 touchbar.js
  2. 安装 Electron:npm install electron
  3. 运行:./node_modules/.bin/electron touchbar.js
  4. 在支持 Touch Bar 的 macOS 设备(或 Touch Bar 模拟器)上即可看到效果。

布局心得与示例结构一一对应:spin 与第一组之间用 large 建立明显分区;三个滚轮标签之间用 small 保持「同组」的紧凑感;末尾再次用 large 把状态结果区隔开。这正是 spacer 最常见的三种用途:分组隔离、同组微距、区块留白

代码级佐证:仓库测试中的组合用法

仓库测试 spec/api-touch-bar-spec.ts 也把 spacer 纳入真实布局做端到端验证——它构造了一个包含按钮、取色器、分组、标签、TouchBarOtherItemsProxy、弹出层、滑块、TouchBarSpacer({ size: 'large' })、分段控件、滚动选择器等多达十余个条目的 TouchBar,随后调用 window.setTouchBar(touchBar) 并验证换绑、escapeItem 动态更新等行为。这说明 TouchBarSpacer 可与任意其他 Touch Bar 条目类自由混排,并且会在 TouchBar 挂载时一并被消费:

const touchBar = new TouchBar({
  items: [
    /* 其他条目…… */
    new TouchBarSpacer({ size: 'large' }),
    new TouchBarSegmentedControl({ /* ... */ })
  ]
});
window.setTouchBar(touchBar);

lib/browser/api/touch-bar.tsTouchBar 实现中,实例挂载最终通过 window._setTouchBarItems(this.orderedItems)(对应方法见 lib/browser/api/touch-bar.ts)把有序条目列表交给原生层,原生侧再按上文 electron_touch_bar.mmidentifiersFromSettings: 逐条翻译成 NSTouchBarItemIdentifier 序列。spacer 的「顺序敏感」因此被严格保留:间隔只作用于左右相邻条目之间,同样的 spacer 放在不同位置会呈现不同布局,这也解释了为什么 items 是一个强调顺序的数组。

注意事项与最佳实践小结

  • 构造期决定大小size 为不可变属性(源码使用 @ImmutableProperty),需要动态调整间距时应重建 TouchBarSpacer 实例并重新 setTouchBar
  • small 是兜底默认值:从原生映射逻辑看,任何无法识别为 large/flexible 的值都会落到 small,但请勿依赖这一容错特性,显式传值可读性更高;
  • flexible 依赖剩余空间:需要把控件推到 Touch Bar 边缘或居中时使用;若条目总宽几乎占满整栏,弹性间隔可能不可见;
  • Mac 限定与实验状态:本 API 面向原生 macOS 应用,且 Electron 官方将其标记为实验性,接口在未来版本中可能调整或移除;
  • 更复杂的分组布局:除了扁平使用 spacer,还可以结合 TouchBarGroup(把多个条目打包成逻辑组)获得更强的结构化布局能力;间隔类与 TouchBarButtonTouchBarLabelTouchBarSegmentedControl 等条目均可自由混排。

如需深入了解整体布局与其余条目,可继续阅读主文档 TouchBar(含完整老虎机示例),或查看相邻条目文档 TouchBarGroupTouchBarOtherItemsProxy

登录后查看全文
热门项目推荐
相关项目推荐