Começar a usar Blocos

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Para começar a fornecer Blocos no app, inclua as dependências abaixo no arquivo build.gradle do app.

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")
}

Criar um Bloco

Para fornecer um Bloco pelo aplicativo, crie uma classe que estenda TileService e implemente os métodos, conforme mostrado neste exemplo de código:

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()
       );
   }
}

Em seguida, adicione um serviço dentro da tag <application> do arquivo AndroidManifest.xml.

<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>

O filtro de permissão e intent registra esse serviço como um provedor de blocos.

O ícone, o rótulo e a descrição são mostrados ao usuário quando ele configura os Blocos no smartphone ou smartwatch.

Use a tag de metadados de visualização para mostrar uma prévia do bloco durante a configuração dele smartphone.

Criar uma IU para Blocos

O layout de um Bloco é criado usando um padrão de construtor. Ele é construído como árvore que consiste em contêineres e elementos básicos de layout. Cada elemento de layout tem propriedades, que podem ser definidas com vários métodos setter.

Elementos básicos de layout

Os elementos visuais abaixo têm suporte:

  • Text: renderiza uma string de texto, opcionalmente a encapsulando.
  • Image: renderiza uma imagem.
  • Spacer: fornece padding entre elementos ou pode atuar como um divisor quando você define a cor do plano de fundo.

Componentes do Material Design

Além dos elementos básicos, a biblioteca tiles-material fornece componentes que garantem um design de Blocos alinhado às recomendações da interface do usuário do Material Design.

  • Button: componente circular clicável projetado para conter um ícone.
  • Chip: componente clicável em formato de estádio projetado para conter até duas linhas de texto e um ícone opcional.
  • CompactChip: componente clicável em formato de estádio projetado para conter uma linha de texto.
  • TitleChip: componente clicável em formato de estádio parecido com um Chip, mas com uma altura maior para acomodar o texto do título.
  • CircularProgressIndicator: indicador circular que pode ser colocado dentro de um ProgressIndicatorLayout para mostrar o progresso ao redor das bordas da tela.

Contêineres de layout

Há suporte para os contêineres abaixo:

  • Row: mostra os elementos filhos horizontalmente, um após o outro.
  • Column: mostra os elementos filhos verticalmente, um após o outro.
  • Box: sobrepõe elementos filhos uns sobre os outros.
  • Arc: mostra os elementos filhos em um círculo.
  • Spannable: aplica FontStyles específicos a seções de texto, além de texto e imagens intercalados. Para mais informações, consulte Spannables.

Cada contêiner pode conter um ou mais filhos, que também podem ser contêineres. Por exemplo, uma Column pode conter vários elementos Row como filhos, resultando em um layout parecido com uma grade.

Um Bloco com um layout de contêiner e dois elementos de layout filhos pode ser parecido com este exemplo:

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();
}

Layouts do Material Design

Além dos layouts básicos, a biblioteca tiles-material fornece alguns layouts opinativos feitos para manter elementos em "slots" específicos.

  • PrimaryLayout: posiciona uma única ação principal CompactChip na parte de baixo com o conteúdo centralizado acima dela.
  • MultiSlotLayout: posiciona os rótulos primário e secundário com conteúdo opcional entre eles e um CompactChip opcional na parte de baixo da tela.
  • ProgressIndicatorLayout: posiciona um CircularProgressIndicator ao redor das bordas da tela e do conteúdo específico dentro dela.

Arcos

Há suporte para os filhos de contêiner Arc abaixo:

  • ArcLine: renderiza uma linha curva ao redor do arco.
  • ArcText: renderiza texto curvado no arco.
  • ArcAdapter: renderiza um elemento básico de layout no arco, mostrado em uma tangente em relação ao arco.

Para mais informações, consulte a documentação de referência de cada um dos tipos de elemento.

Modificadores

Como alternativa, todos os elementos de layout disponíveis podem ter modificadores. Use esses modificadores para as finalidades abaixo:

  • Mudar a aparência do layout. Por exemplo, adicionar um plano de fundo, uma borda ou um padding ao elemento de layout.
  • Adicionar metadados sobre o layout. Por exemplo, adicionar um modificador de semântica ao elemento de layout que vai ser usado por leitores de tela.
  • Adicionar funcionalidade. Por exemplo, adicione um modificador clicável ao elemento de layout para tornar o Bloco interativo. Para mais informações, consulte Interagir com o Bloco.

Por exemplo, podemos personalizar a aparência e os metadados padrão de uma Image, conforme mostrado neste exemplo de código:

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();
}

Spannables

Um Spannable é um tipo especial de contêiner que apresenta elementos de maneira parecida com um texto. Isso é útil quando você quer aplicar um estilo diferente a apenas uma substring em um bloco de texto maior, algo que não é possível com o elemento Text.

Um contêiner Spannable é preenchido com filhos Span. Outros filhos ou instâncias Spannable aninhadas não são permitidos.

Há dois tipos de filhos Span:

  • SpanText: renderiza o texto com um estilo específico.
  • SpanImage: renderiza uma imagem inline com texto.

Por exemplo, você pode aplicar itálico à palavra "world" em um Bloco "Hello world" e inserir uma imagem entre as palavras, conforme mostrado neste exemplo de código:

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();
}

Trabalhar com recursos

Os Blocos não têm acesso a nenhum dos recursos do seu app. Isso significa que você não pode transmitir um ID de imagem do Android a um elemento de layout Image e esperar que ele seja resolvido. Em vez disso, substitua o método onResourcesRequest() e forneça os recursos manualmente.

Há duas maneiras de fornecer imagens no método 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()
);
}