开始使用卡片

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

如需开始在应用中提供卡片,请在应用的 build.gradle 文件中添加以下依赖项。

Groovy

dependencies {
    // Use to implement support for wear tiles
    implementation "androidx.wear.tiles:tiles:1.1.0"

    // Use to utilize components and layouts with Material Design in your tiles
    implementation "androidx.wear.tiles:tiles-material:1.1.0"

    // Use to preview wear tiles in your own app
    debugImplementation "androidx.wear.tiles:tiles-renderer:1.1.0"

    // Use to fetch tiles from a tile provider in your tests
    testImplementation "androidx.wear.tiles:tiles-testing:1.1.0"
}

Kotlin

dependencies {
    // Use to implement support for wear tiles
    implementation("androidx.wear.tiles:tiles:1.1.0")

    // Use to utilize components and layouts with Material design in your tiles
    implementation("androidx.wear.tiles:tiles-material:1.1.0")

    // Use to preview wear tiles in your own app
    debugImplementation("androidx.wear.tiles:tiles-renderer:1.1.0")

    // Use to fetch tiles from a tile provider in your tests
    testImplementation("androidx.wear.tiles:tiles-testing:1.1.0")
}

创建卡片

如需在应用中提供卡片,请创建一个扩展 TileService 的类并实现方法,如以下代码示例所示:

Kotlin

private val RESOURCES_VERSION = "1"
class MyTileService : TileService() {
    override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
        Futures.immediateFuture(Tile.Builder()
            .setResourcesVersion(RESOURCES_VERSION)
            .setTimeline(Timeline.Builder().addTimelineEntry(
                TimelineEntry.Builder().setLayout(
                    Layout.Builder().setRoot(
                        Text.Builder().setText("Hello world!").setFontStyle(
                            FontStyle.Builder().setColor(argb(0xFF000000)).build()
                        ).build()
                    ).build()
                ).build()
            ).build()
        ).build())

    override fun onResourcesRequest(requestParams: ResourcesRequest) =
        Futures.immediateFuture(Resources.Builder()
            .setVersion(RESOURCES_VERSION)
            .build()
        )
}

Java

public class MyTileService extends TileService {
    private static final String RESOURCES_VERSION = "1";

    @NonNull
    @Override
    protected ListenableFuture<Tile> onTileRequest(
        @NonNull TileRequest requestParams
    ) {
        return Futures.immediateFuture(new Tile.Builder()
            .setResourcesVersion(RESOURCES_VERSION)
            .setTimeline(new Timeline.Builder()
                .addTimelineEntry(new TimelineEntry.Builder()
                    .setLayout(new Layout.Builder()
                        .setRoot(new Text.Builder()
                            .setText("Hello world!")
                            .setFontStyle(new FontStyle.Builder()
                                .setColor(argb(0xFF000000)).build()
                            ).build()
                        ).build()
                    ).build()
                ).build()
            ).build()
        );
   }

   @NonNull
   @Override
   protected ListenableFuture<Resources> onResourcesRequest(
       @NonNull ResourcesRequest requestParams
   ) {
       return Futures.immediateFuture(new Resources.Builder()
               .setVersion(RESOURCES_VERSION)
               .build()
       );
   }
}

接下来,在 AndroidManifest.xml 文件的 <application> 标记内添加服务。

<service
   android:name=".MyTileService"
   android:label="@string/tile_label"
   android:description="@string/tile_description"
   android:exported="true"
   android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
   <intent-filter>
       <action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
   </intent-filter>

   <meta-data android:name="androidx.wear.tiles.PREVIEW"
       android:resource="@drawable/tile_preview" />
</service>

权限和 intent 过滤器会将此服务注册为卡片提供程序。

当用户在手机或手表上配置卡片时,系统会向用户显示图标、标签和说明。

借助预览元数据标记,当用户在手机上配置卡片时,可以显示卡片的预览。

为卡片创建界面

卡片的布局是使用构建器模式编写的。卡片布局的构建形式就像是一棵由布局容器和基本布局元素组成的树。每个布局元素都有其属性,您可以通过各种 setter 方法设置这些属性。

基本布局元素

支持以下视觉元素:

  • Text:渲染文本字符串,可选择是否换行。
  • Image:渲染图片。
  • Spacer:设置元素之间的内边距,也可在设置背景颜色时用作分隔线。

Material 组件

除了基本元素之外,tiles-material 库还提供了一些组件,用于确保卡片设计符合 Material Design 界面建议。

  • Button:可点击的圆形组件,用于包含图标。
  • Chip:可点击的体育场形组件,最多可包含两行文本和一个可选图标。
  • CompactChip:可点击的体育场形组件,用于包含一行文本。
  • TitleChip:可点击的体育场形组件,与 Chip 类似但高度更高,可容纳标题文本。
  • CircularProgressIndicator:可放在 ProgressIndicatorLayout 内的圆形进度指示器,用于围绕屏幕边缘显示进度。

布局容器

支持以下容器:

  • Row:一个接一个地水平排列子元素。
  • Column:一个接一个地垂直排列子元素。
  • Box:将一个子元素叠加在另一个子元素上。
  • Arc:沿着环形排列子元素。
  • Spannable:将特定的 FontStyles 应用于文本的某些部分以及交错文本和图片。如需了解详情,请参阅 Spannable

每个容器可以包含一个或多个子元素,这些子元素本身也可以是容器。例如,Column 可以包含多个 Row 元素作为子元素,从而形成类似于网格的布局。

作为参考,由一个容器布局和两个子布局元素组成的卡片可能如下所示:

Kotlin

private fun myLayout(): LayoutElement =
    Row.Builder()
        .setWidth(wrap())
        .setHeight(expand())
        .setVerticalAlignment(VALIGN_BOTTOM)
        .addContent(Text.Builder()
            .setText("Hello world")
            .build()
        )
        .addContent(Image.Builder()
            .setResourceId("image_id")
            .setWidth(dp(24f))
            .setHeight(dp(24f))
            .build()
        ).build()

Java

private LayoutElement myLayout() {
    return new Row.Builder()
        .setWidth(wrap())
        .setHeight(expand())
        .setVerticalAlignment(VALIGN_BOTTOM)
        .addContent(new Text.Builder()
            .setText("Hello world")
            .build()
        )
        .addContent(new Image.Builder()
            .setResourceId("image_id")
            .setWidth(dp(24f))
            .setHeight(dp(24f))
            .build()
        ).build();
}

Material 布局

除了基本布局之外,tiles-material 库还提供几种固定布局,用于将元素放到特定的“槽位”中。

  • PrimaryLayout:将单个主要操作 CompactChip 放在底部,内容居中置于其上。
  • MultiSlotLayout:放置主标签和次级标签,在两个标签之间放置可选内容,并在底部放置可选的 CompactChip
  • ProgressIndicatorLayout:围绕着屏幕边缘放置 CircularProgressIndicator,内部放置指定内容。

弧形

支持以下 Arc 容器子元素:

  • ArcLine:沿着弧形渲染一条曲线。
  • ArcText:沿着弧形渲染曲线文本。
  • ArcAdapter:沿着弧形渲染基本布局元素,在弧线的切线方向上进行绘制。

如需了解详情,请参阅每种元素类型的参考文档

修饰符

对于每种可用的布局元素,您都可以选择对其应用修饰符。这些修饰符可用于以下用途:

  • 更改布局的视觉外观。例如,为布局元素添加背景、边框或内边距。
  • 添加有关布局的元数据。例如,为布局元素添加 semantics 修饰符,以便与屏幕阅读器结合使用。
  • 添加功能。例如,为布局元素添加 clickable 修饰符,使用户可与卡片互动。如需了解详情,请参阅与卡片互动

例如,我们可以自定义 Image 的默认外观和元数据,如以下代码示例所示:

Kotlin

private fun myImage(): LayoutElement =
    Image.Builder()
        .setWidth(dp(24f))
        .setHeight(dp(24f))
        .setResourceId("image_id")
        .setModifiers(Modifiers.Builder()
            .setBackground(Background.Builder().setColor(argb(0xFFFF0000)).build())
            .setPadding(Padding.Builder().setStart(dp(12f)).build())
            .setSemantics(Semantics.builder()
                .setContentDescription("Image description")
                .build()
            ).build()
        ).build()

Java

private LayoutElement myImage() {
   return new Image.Builder()
           .setWidth(dp(24f))
           .setHeight(dp(24f))
           .setResourceId("image_id")
           .setModifiers(new Modifiers.Builder()
                   .setBackground(new Background.Builder().setColor(argb(0xFFFF0000)).build())
                   .setPadding(new Padding.Builder().setStart(dp(12f)).build())
                   .setSemantics(new Semantics.Builder()
                           .setContentDescription("Image description")
                           .build()
                   ).build()
           ).build();
}

Spannable

Spannable 是一种特殊的容器,其元素布局方式与文本类似。如果您想仅针对一大段文本中的一个子字符串应用不同样式,使用 Text 元素是不可能实现的,此时 Spannable 就非常有用。

Spannable 容器中填充的是 Span 子元素。不允许填充其他子元素或嵌套的 Spannable 实例。

Span 子元素有两种类型:

  • SpanText:渲染特定样式的文本。
  • SpanImage:渲染内嵌文本的图片。

例如,您可以将“Hello world”卡片中的“world”设为斜体,并在两个单词之间插入图片,如以下代码示例所示:

Kotlin

private fun mySpannable(): LayoutElement =
    Spannable.Builder()
        .addSpan(SpanText.Builder()
            .setText("Hello ")
            .build()
        )
        .addSpan(SpanImage.Builder()
            .setWidth(dp(24f))
            .setHeight(dp(24f))
            .setResourceId("image_id")
            .build()
        )
        .addSpan(SpanText.Builder()
            .setText("world")
            .setFontStyle(FontStyle.Builder()
                .setItalic(true)
                .build())
            .build()
        ).build()

Java

private LayoutElement mySpannable() {
   return new Spannable.Builder()
        .addSpan(new SpanText.Builder()
            .setText("Hello ")
            .build()
        )
        .addSpan(new SpanImage.Builder()
            .setWidth(dp(24f))
            .setHeight(dp(24f))
            .setResourceId("image_id")
            .build()
        )
        .addSpan(new SpanText.Builder()
            .setText("world")
            .setFontStyle(newFontStyle.Builder()
                .setItalic(true)
                .build())
            .build()
        ).build();
}

使用资源

卡片无法访问应用的任何资源。这意味着您无法将 Android 图片 ID 传递给 Image 布局元素并指望应用能够对其进行解析。请替换 onResourcesRequest() 方法并手动提供任何资源。

onResourcesRequest() 方法中,您可以通过以下两种方式提供图片:

Kotlin

override fun onResourcesRequest(
    requestParams: ResourcesRequest
) = Futures.immediateFuture(
Resources.Builder()
    .setVersion("1")
    .addIdToImageMapping("image_from_resource", ImageResource.Builder()
        .setAndroidResourceByResId(AndroidImageResourceByResId.Builder()
            .setResourceId(R.drawable.image_id)
            .build()
        ).build()
    )
    .addIdToImageMapping("image_inline", ImageResource.Builder()
        .setInlineResource(InlineImageResource.Builder()
            .setData(imageAsByteArray)
            .setWidthPx(48)
            .setHeightPx(48)
            .setFormat(ResourceBuilders.IMAGE_FORMAT_RGB_565)
            .build()
        ).build()
    ).build()
)

Java

@Override
protected ListenableFuture<Resources> onResourcesRequest(
       @NonNull ResourcesRequest requestParams
) {
return Futures.immediateFuture(
    new Resources.Builder()
        .setVersion("1")
        .addIdToImageMapping("image_from_resource", new ImageResource.Builder()
            .setAndroidResourceByResId(new AndroidImageResourceByResId.Builder()
                .setResourceId(R.drawable.image_id)
                .build()
            ).build()
        )
        .addIdToImageMapping("image_inline", new ImageResource.Builder()
            .setInlineResource(new InlineImageResource.Builder()
                .setData(imageAsByteArray)
                .setWidthPx(48)
                .setHeightPx(48)
                .setFormat(ResourceBuilders.IMAGE_FORMAT_RGB_565)
                .build()
            ).build()
        ).build()
);
}