widget

widget 是一种界面元素,可提供以下一项或多项功能:

  • 其他 widget(例如卡片和部分)的结构
  • 向用户显示的信息,例如文字和图片,或
  • 操作提示,例如按钮、文本输入字段或复选框。

添加到卡片部分的 widget 集定义了整个插件界面。widget 在网站和移动设备上的外观和功能相同。参考文档介绍了构建 widget 集的几种方法。

微件类型

插件 widget 通常分为三类:结构 widget、信息 widget 和用户互动 widget。

结构微件

结构性 widget 可为界面中使用的其他 widget 提供容器和组织结构。

  • 按钮集:一个或多个文字或图片按钮的集合,以水平行分组在一起。
  • 卡片:包含一个或多个卡片部分的单个情境卡片。通过配置卡片导航,定义用户在卡片之间的移动方式。
  • 卡片标题:相应卡片的标题。卡片标题可以包含标题、副标题和图片。卡片操作通用操作(如果使用)会显示在卡片标题中。
  • 卡片部分:一组收集的 widget,通过水平线与其他卡片部分分隔开,并且可以选择性地包含部分标题。每张卡片必须至少包含一个卡片部分。您无法向卡片部分添加卡片或卡片标题。

显示结构化 widget 的卡片示例

向某个容器添加 widget 时,您会创建并添加该 widget 的副本。如果您在添加微件后对其进行更改,相应更改不会反映在界面中。请确保微件已完成,然后再添加。 如果您需要在添加 widget 后对其进行更改,请重新构建整个卡片部分或卡片。如需了解详情,请参阅构建卡片

除了这些基本结构微件之外,您还可以在 Google Workspace 加载项中使用 Card 服务来创建与当前卡片重叠的结构:固定页脚预览卡片

您可以在卡片的底部添加一组固定的按钮。此行不会随卡片内容的其余部分移动或滚动。

固定页脚 widget 示例

以下代码摘录展示了如何定义一个固定的页脚示例并将其添加到卡片中:

var fixedFooter = CardService.newFixedFooter()
    .setPrimaryButton(
        CardService.newTextButton()
            .setText("Primary")
            .setOpenLink(CardService.newOpenLink()
                .setUrl("https://www.google.com")))
    .setSecondaryButton(
        CardService.newTextButton()
            .setText("Secondary")
            .setOnClickAction(
                CardService.newAction()
                    .setFunctionName(
                        "secondaryCallback")));

var card = CardService.newCardBuilder()
    // (...)
    .setFixedFooter(fixedFooter)
    .build();

提示卡

预览卡片通知示例

当用户操作(例如打开 Gmail 邮件)触发新的情境化内容时,您可以立即显示新的情境化内容(默认行为),也可以在边栏底部显示滑出式卡片通知。如果用户在情境触发器处于有效状态时点击“返回”图标 返回到您的首页,系统会显示预览卡片,帮助用户再次找到情境内容。

如需在有新的情境相关内容时显示预览卡片,请将 .setDisplayStyle(CardService.DisplayStyle.PEEK) 添加到 CardBuilder 类中。只有在返回的单个卡片对象包含上下文触发器时,才会显示预览卡;否则,返回的卡片会替换当前卡片。

如需自定义预览卡片的标题,请在构建情境卡片时添加包含标准 CardHeader 对象的 .setPeekCardHeader 方法。默认情况下,Peek 卡片标题仅包含插件的名称。 自定义预览卡片示例

根据 Cats Google Workspace 加载项快速入门,以下代码会通过 Peek 卡片向用户通知新的情境化内容,并自定义 Peek 卡片的标题以显示所选 Gmail 邮件会话的主题。

var peekHeader = CardService.newCardHeader()
    .setTitle('Contextual Cat')
    .setImageUrl('https://www.gstatic.com/images/
        icons/material/system/1x/pets_black_48dp.png')
    .setSubtitle(text);

. . .

var card = CardService.newCardBuilder()
    .setDisplayStyle(CardService.DisplayStyle.PEEK)
    .setPeekCardHeader(peekHeader);

信息微件

信息类 widget 向用户显示信息。

  • 图片:由托管且可公开访问的网址指示的图片。
  • DecoratedText:一个文本内容字符串,可与其他元素(例如顶部和底部标签,以及图片或图标)搭配使用。DecoratedText widget 还可以包含 ButtonSwitch widget。添加的开关可以是切换开关,也可以是复选框。内容文本可以使用 HTML 格式;顶部和底部标签必须使用纯文本。
  • 文本段落:文本段落,可包含 HTML 格式的元素。

卡片中的信息类微件示例

用户互动微件

用户互动 widget 可让插件响应用户操作。您可以使用操作响应来配置这些 widget,以显示不同的卡片、打开网址、显示通知、撰写电子邮件草稿或运行其他 Apps 脚本函数。如需了解详情,请参阅构建互动式卡片指南。

  • 卡片操作:放置在插件标题栏菜单中的菜单项。标题栏菜单还可以包含定义为通用操作的项,这些项会显示在插件定义的每个卡片上。
  • 日期时间选择器:微件允许用户选择日期、时间或同时选择两者。如需了解详情,请参阅日期和时间选择器
  • 图片按钮:使用图片而非文字的按钮。使用多个预定义的图标之一或公开托管的图片。
  • 选择输入:表示选项集合的输入字段。选择输入微件以复选框、单选按钮或下拉选择框的形式呈现。
  • Switch:与 DecoratedText widget 搭配使用的切换 widget。默认情况下,这些设置会显示为切换开关,但您可以将其显示为复选框
  • 文本按钮:带有文本标签的按钮。为文字按钮指定背景颜色填充(默认值为透明)。您还可以根据需要停用该按钮。
  • 文本输入:文本输入字段。该 widget 可以包含标题文本、提示文本和多行文本。当文本值发生变化时,该 widget 可以触发操作。
  • 网格:一种多列布局。使用图片、标题、副标题和自定义选项(例如边框和裁剪样式)来表示商品。
显示卡片操作的菜单示例 卡片中的用户互动 widget 示例

DecoratedText 复选框

您可以定义一个附加了复选框的 DecoratedText widget,而不是按钮或二元切换开关。与切换开关类似,复选框的值包含在通过 setOnClickAction 方法传递给附加到此 DecoratedTextAction操作事件对象中。

带装饰文本的复选框 widget 示例

以下代码段展示了如何定义要添加到卡片中的复选框 DecoratedText widget:

var decoratedText = CardService.newDecoratedText()
    // (...)
    .setSwitch(CardService.newSwitch()
        .setFieldName('form_input_switch_key')
        .setValue('switch_is_on')
        .setControlType(
            CardService.SwitchControlType.CHECK_BOX));

日期和时间选择器

定义允许用户选择时间、日期或同时选择两者的小组件。使用 setOnChangeAction 可分配一个微件处理程序函数,以便在选择器的值发生变化时执行该函数。

自定义预览卡片示例

以下代码摘录展示了如何定义仅限日期选择器、仅限时间选择器和日期时间选择器以添加到卡片中:

var dateOnlyPicker = CardService.newDatePicker()
    .setTitle("Enter a date")
    .setFieldName("date_field")
    // Set default value as May 24 2019. Either a
    // number or string is acceptable.
    .setValueInMsSinceEpoch(1558668600000)
    .setOnChangeAction(CardService.newAction()
        .setFunctionName("handleDateChange"));

var timeOnlyPicker = CardService.newTimePicker()
    .setTitle("Enter a time")
    .setFieldName("time_field")
    // Set default value as 23:30.
    .setHours(23)
    .setMinutes(30)
    .setOnChangeAction(CardService.newAction()
        .setFunctionName("handleTimeChange"));

var dateTimePicker = CardService.newDateTimePicker()
    .setTitle("Enter a date and time")
    .setFieldName("date_time_field")
    // Set default value as May 24 2019 03:30 AM UTC.
    // Either a number or string is acceptable.
    .setValueInMsSinceEpoch(1558668600000)
    // EDT time is 4 hours behind UTC.
    .setTimeZoneOffsetInMins(-4 * 60)
    .setOnChangeAction(CardService.newAction()
        .setFunctionName("handleDateTimeChange"));

以下是日期时间选择器微件处理程序函数的一个示例。此处理程序用于格式化并记录字符串,该字符串表示用户在 ID 为 myDateTimePickerWidgetID 的日期时间选择器 widget 中选择的日期时间:

function handleDateTimeChange(event) {
  var dateTimeInput =
    event.commonEventObject.formInputs["myDateTimePickerWidgetID"];
  var msSinceEpoch = dateTimeInput.msSinceEpoch;
  var hasDate = dateTimeInput.hasDate;
  var hasTime = dateTimeInput.hadTime;

  // The following requires you to configure the add-on to read user locale
  // and timezone.
  // See:
  // https://developers.google.com/workspace/add-ons/how-tos/access-user-locale
  var userTimezoneId = event.userTimezone.id;

  // Format and log the date-time selected using the user's timezone.
  var formattedDateTime;
  if (hasDate && hasTime) {
    formattedDateTime = Utilities.formatDate(
      new Date(msSinceEpoch), userTimezoneId, "yyy/MM/dd hh:mm:ss");
  } else if (hasDate) {
    formattedDateTime = Utilities.formatDate(
      new Date(msSinceEpoch), userTimezoneId, "yyy/MM/dd")
      + ", Time unspecified";
  } else if (hasTime) {
    formattedDateTime = "Date unspecified, "
      + Utilities.formatDate(
          new Date(msSinceEpoch), userTimezoneId, "hh:mm a");
  }

  if (formattedDateTime) {
    console.log(formattedDateTime);
  }
}

 

下表显示了桌面设备和移动设备上的选择器选择界面示例。选中后,日期选择器会打开一个基于月份的日历界面,供用户选择新日期。

当用户在桌面设备上选择时间选择器时,系统会打开一个下拉菜单,其中列出了以 30 分钟为增量的时间。用户也可以输入具体时间。在移动设备上,选择时间选择器会打开内置的移动“时钟”时间选择器。

桌面设备 移动设备
日期选择器选择示例 移动日期选择器选择示例
时间选择器选择示例 移动时间选择器选择示例

网格

使用网格 widget 以多列布局显示内容。每个项都可以显示图片、标题和副标题。使用其他配置选项来设置网格项中文字相对于图片的位置。

配置一个网格项,其标识符作为参数返回到网格上定义的操作。

显示联系信息的网格 widget 示例

var gridItem = CardService.newGridItem()
  .setIdentifier("item_001")
  .setTitle("Lucian R.")
  .setSubtitle("Chief Information Officer")
  .setImage(imageComponent);

var cropStyle = CardService.newImageCropStyle()
  .setImageCropType(CardService.ImageCropType.RECTANGLE_4_3);

var imageComponent = CardService.newImageComponent()
  .setImageUrl("https://developers.google.com/workspace/
      images/cymbal/people/person1.jpeg")
  .setCropStyle(cropStyle)

var grid = CardService.newGrid()
  .setTitle("Recently viewed")
  .addItem(gridItem)
  .setNumColumns(2)
  .setOnClickAction(CardService.newAction()
    .setFunctionName("handleGridItemClick"));

文本格式

某些基于文本的 widget 支持基本的文本 HTML 格式。设置这些 widget 的文本内容时,请添加相应的 HTML 标记。

下表显示了支持的标记及其用途:

格式 示例 呈现的结果
粗体 "This is <b>bold</b>." 这是粗体
斜体 "This is <i>italics</i>." 这是斜体
下划线 "This is <u>underline</u>." 这是下划线
删除线 "This is <s>strikethrough</s>." 这是删除线
字体颜色 "This is <font color=\"#FF0000\">red font</font>." 这是红色字体
超链接 "This is a <a href=\"https://www.google.com\">hyperlink</a>." 这是一个超链接
时间 "This is a time format: <time>2023-02-16 15:00</time>." 这是一种时间格式:
换行符 "This is the first line. <br> This is a new line. 这是第一行。
这是新的一行。