Kartları kullanmaya başlayın

Uygulamanızdan kart sağlamaya başlamak için aşağıdaki bağımlılıkları uygulamanızın build.gradle dosyasına ekleyin.

Modern

dependencies {
    // Use to implement support for wear tiles
    implementation "androidx.wear.tiles:tiles:1.4.0-alpha04"

    // Use to utilize standard components and layouts in your tiles
    implementation "androidx.wear.protolayout:protolayout:1.2.0-alpha04"

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

    // Use to include dynamic expressions in your tiles
    implementation "androidx.wear.protolayout:protolayout-expression:1.2.0-alpha04"

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

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

Kotlin

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

    // Use to utilize standard components and layouts in your tiles
    implementation("androidx.wear.protolayout:protolayout:1.2.0-alpha04")

    // Use to utilize components and layouts with Material Design in your tiles
    implementation("androidx.wear.protolayout:protolayout-material:1.2.0-alpha04")

    // Use to include dynamic expressions in your tiles
    implementation("androidx.wear.protolayout:protolayout-expression:1.2.0-alpha04")

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

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

Kart oluştur

Uygulamanızdan döşeme sağlamak için TileService öğesini genişleten bir sınıf oluşturun ve aşağıdaki kod örneğindeki gibi yöntemleri uygulayın:

Kotlin

// Uses the ProtoLayout namespace for tile timeline objects.
// If you haven't done so already, migrate to the ProtoLayout namespace.
import androidx.wear.protolayout.TimelineBuilders.Timeline
import androidx.wear.protolayout.material.Text
import androidx.wear.tiles.TileBuilders.Tile

private val RESOURCES_VERSION = "1"
class MyTileService : TileService() {
    override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
        Futures.immediateFuture(Tile.Builder()
            .setResourcesVersion(RESOURCES_VERSION)
            .setTileTimeline(
                Timeline.fromLayoutElement(
                    Text.Builder(this, "Hello world!")
                        .setTypography(Typography.TYPOGRAPHY_DISPLAY1)
                        .setColor(argb(0xFF000000.toInt()))
                        .build()))
            .build())

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

Java

// Uses the ProtoLayout namespace for tile timeline objects.
// If you haven't done so already, migrate to the ProtoLayout namespace.
import androidx.wear.protolayout.TimelineBuilders.Timeline;
import androidx.wear.protolayout.material.Text;
import androidx.wear.tiles.TileBuilders.Tile;

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)
            .setTileTimeline(
                Timeline.fromLayoutElement(
                    new Text.Builder(this, "Hello world!")
                        .setTypography(Typography.TYPOGRAPHY_DISPLAY1)
                        .setColor(ColorBuilders.argb(0xFF000000))
                        .build()))
            .build()
        );
   }

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

Sonra, AndroidManifest.xml dosyanızın <application> etiketine bir hizmet ekleyin.

<service
   android:name=".MyTileService"
   android:label="@string/tile_label"
   android:description="@string/tile_description"
   android:icon="@drawable/tile_icon_round"
   android:roundIcon="@drawable/tile_icon_round"
   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>

İzin ve intent filtresi, bu hizmeti bir karo sağlayıcı olarak kaydeder.

Kullanıcı, telefonunda veya kol saatinde kartları yapılandırdığında simge, etiket ve açıklama gösterilir.

Telefonunuzda yapılandırırken karonun önizlemesini göstermek için önizleme meta veri etiketini kullanın.

Kutu hizmeti yaşam döngüsüne genel bakış

Uygulama manifestinizde TileService oluşturup beyan ettikten sonra blok hizmetinin durum değişikliklerine yanıt verebilirsiniz.

TileService, bir [bağlı hizmettir][37]. TileService, uygulama isteğinizin bir sonucu olarak veya sistemin bununla iletişim kurması gerekiyorsa bağlandı. Tipik bir [bound-hizmet yaşam döngüsü][38] şu dört geri çağırma yöntemini içerir: [onCreate()][39], [onBind()][40], [onUnbind()][41] ve [onDestroy()][42]. Hizmet yeni bir yaşam döngüsü aşamasına her geçtiğinde sistem bu yöntemleri çağırır.

Sınır hizmet yaşam döngüsünü kontrol eden geri çağırmalara ek olarak TileService yaşam döngüsüne özgü başka yöntemler de uygulayabilirsiniz. Sistemden gelen güncelleme isteklerine yanıt vermek için tüm karo hizmetleri onTileRequest() ve onTileResourcesRequest() özelliklerini uygulamalıdır.

  • [onTileAddEvent()][43]: Sistem, bu yöntemi yalnızca kullanıcı, karonuzu ilk kez eklediğinde ve kullanıcı, kartı kaldırıp tekrar eklediğinde çağırır. Tek seferlik başlatma işlemi için en uygun zaman budur.

    onTileAddEvent(), sistem tarafından bir kart oluşturulduğunda değil, yalnızca karo grubu yeniden yapılandırıldığında çağrılır. Örneğin, cihaz yeniden başlatıldığında veya açıldığında, onTileAddEvent() önceden eklenmiş olan kutular için çağrılmaz. Size ait hangi kartların etkin olduğunun anlık görüntüsünü almak için [getActiveTilesAsync()][50] değerini kullanabilirsiniz.

  • [onTileRemoveEvent()][44]: Sistem, yalnızca kullanıcı karonuzu kaldırırsa bu yöntemi çağırır.

  • [onTileEnterEvent()][45]: Bu sağlayıcı tarafından sağlanan bir kart ekranda göründüğünde sistem bu yöntemi çağırır.

  • [onTileLeaveEvent()][46]: Bu sağlayıcı tarafından sağlanan bir kart ekranda görünmediğinde sistem bu yöntemi çağırır.

  • [onTileRequest()][47]: Sistem, bu sağlayıcıdan yeni bir [zaman çizelgesi][51] istediğinde sistem bu yöntemi çağırır.

  • [onTileResourcesRequest()][48]: Sistem, bu sağlayıcıdan bir [kaynak paketi][49] istediğinde sistem bu yöntemi çağırır. Bu durum, Kart ilk kez yüklenirken veya kaynak sürümü değiştiğinde gerçekleşebilir.

Etkin olan karoları sorgulama

Etkin kutular, kol saatinde gösterilmek üzere eklenen kartlardır. Uygulamanıza ait hangi kartların etkin olduğunu sorgulamak için TileService statik yöntemini [getActiveTilesAsync()][50] kullanın.

Kartlar için kullanıcı arayüzü oluşturma

Karo düzeni, oluşturucu deseni kullanılarak yazılmıştır. Karoların düzeni, düzen kapsayıcılarından ve temel düzen öğelerinden oluşan bir ağaç gibi oluşturulur. Her düzen öğesinin, çeşitli belirleyici yöntemleriyle ayarlayabileceğiniz özellikleri vardır.

Temel düzen öğeleri

[Materyal bileşenleri][2] ile birlikte protolayout kitaplığından aşağıdaki görsel öğeler desteklenir:

  • [Text][3]: İsteğe bağlı olarak sarmalanan bir metin dizesi oluşturur.
  • [Image][4]: bir resim oluşturur.
  • [Spacer][5]: Öğeler arasında dolgu sağlar veya arka plan rengini ayarladığınızda ayırıcı olarak kullanılabilir.

Malzeme bileşenleri

protolayout-material kitaplığı, temel öğelere ek olarak, Materyal Tasarım kullanıcı arayüzü önerilerine uygun karo tasarımını sağlayan bileşenler de sunar.

  • [Button][6]: bir simge içerecek şekilde tasarlanmış tıklanabilir yuvarlak bileşen.
  • [Chip][7]: En fazla iki satır metin ve isteğe bağlı bir simge içerecek şekilde tasarlanmış, stadyum şekilli tıklanabilir bileşen.

  • [CompactChip][9]: Bir metin satırı içerecek şekilde tasarlanmış stadyum şekilli tıklanabilir bileşen.

  • [TitleChip][10]: Chip benzeri, ancak başlık metnini yerleştirmek için daha geniş yüksekliğe sahip, stadyum şekilli tıklanabilir bileşen.

  • [CircularProgressIndicator][11]: Ekranın kenarlarındaki ilerlemeyi görüntülemek için EdgeContentLayout içine yerleştirilebilen dairesel ilerleme göstergesi.

Düzen kapsayıcıları

[Material düzenler][12] ile birlikte şu container'lar desteklenmektedir:

  • [Row][13]: Alt öğeleri yatay olarak, birbiri ardına yerleştirir.
  • [Column][14]: Alt öğeleri dikey olarak art arda yerleştirir.
  • [Box][15]: Alt öğeleri birbirinin üzerine yerleştirir.
  • [Arc][16]: Alt öğeleri bir daire içine yerleştirir.
  • [Spannable][17]: Boşluk içeren metin ve resimlerle birlikte metin bölümlerine belirli [FontStyles][18] ifadesini uygular. Daha fazla bilgi için [Spannables][19] bölümüne bakın.

Her kapsayıcıda, kendileri de kapsayıcı olabilecek bir veya daha fazla alt öğe bulunabilir. Örneğin, bir Column alt öğe olarak birden fazla Row öğesi içerebilir. Bu da ızgara benzeri bir düzene neden olur.

Örneğin, kapsayıcı düzeni ve iki alt düzen öğesine sahip karo şöyle görünebilir:

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

Materyal düzenleri

protolayout-material kitaplığı, temel düzenlere ek olarak öğeleri belirli "alanlarda" tutmak için oluşturulmuş birkaç fikirli düzen sağlar.

  • [PrimaryLayout][20]: İçerik ortalanmış olarak en altta tek bir birincil işlem CompactChip konumlandırır.

  • [MultiSlotLayout][22]: Birincil ve ikincil etiketleri, aralarında isteğe bağlı içerikle birlikte, isteğe bağlı bir CompactChip ise en altta konumlandırır.

  • [MultiButtonLayout][23]: Materyal yönergelerine göre düzenlenmiş bir dizi düğme konumlar.

  • [EdgeContentLayout][24]: İçeriği ekranın kenarının etrafına yerleştirir (ör. CircularProgressIndicator). Bu düzeni kullanırken içeriğindeki içerik uygun kenar boşlukları ve dolgu otomatik olarak uygulanır.

Yaylar

Aşağıdaki Arc kapsayıcı alt öğeleri desteklenir:

  • [ArcLine][25]: Yayının çevresinde eğri bir çizgi oluşturur.
  • [ArcText][26]: Arc'da eğri metin oluşturur.
  • [ArcAdapter][27]: Yayın içinde, yayına teğet olarak çizilmiş bir temel düzen öğesi oluşturur.

Daha fazla bilgi için her bir öğe türüyle ilgili [referans belgelerine][28] bakın.

Değiştiriciler

Kullanılabilir her düzen öğesine isteğe bağlı olarak değiştiriciler uygulanabilir. Bu değiştiricileri aşağıdaki amaçlar için kullanın:

  • Düzenin görsel görünümünü değiştirin. Örneğin, düzen öğenize arka plan, kenarlık veya dolgu ekleyin.
  • Düzen hakkında meta veri ekleyin. Örneğin, ekran okuyucularla kullanmak için düzen öğenize bir anlam değiştirici ekleyin.
  • İşlevsellik ekleyin. Örneğin, blokunuzu etkileşimli hale getirmek için düzen öğenize tıklanabilir bir değiştirici ekleyin. Daha fazla bilgi için [Karolarla etkileşim kurma][29] konusuna bakın.

Örneğin, aşağıdaki kod örneğinde gösterildiği gibi [Image][4] öğesinin varsayılan görünümünü ve meta verilerini özelleştirebiliriz:

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

Genişletilebilir Öğeler

Spannable, öğeleri metne benzer şekilde yerleştiren özel bir kapsayıcı türüdür. Bu, daha büyük bir metin blokundaki yalnızca bir alt dizeye farklı bir stil uygulamak istediğinizde yararlı olur. Bu durum, Text öğesiyle mümkün olmayabilir.

Spannable kapsayıcısı [Span][31] alt öğe ile doldurulur. Diğer alt öğelere veya iç içe yerleştirilmiş Spannable örneklerine izin verilmez.

İki tür Span alt öğesi vardır:

  • [SpanText][32]: Belirli bir stile sahip metni oluşturur.
  • [SpanImage][33]: bir resmi metinle satır içinde oluşturur.

Örneğin, bir "Merhaba dünya" karosundaki "dünya"yı italik hale getirebilir ve aşağıdaki kod örneğinde gösterildiği gibi kelimelerin arasına bir resim ekleyebilirsiniz:

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

Kaynaklarla çalışma

Kutuların, uygulamanızın hiçbir kaynağına erişimi yok. Yani bir Image düzen öğesine Android resim kimliği iletemez ve bu kimliğin çözümlenmesini bekleyemezsiniz. Bunun yerine [onTileResourcesRequest()][34] yöntemini geçersiz kılın ve tüm kaynakları manuel olarak sağlayın.

onTileResourcesRequest() yönteminde görüntü sağlamanın iki yolu vardır:

  • [setAndroidResourceByResId()][35] kullanarak çekilebilir bir kaynak sağlayın.
  • [setInlineResource()][36] işlevini kullanarak ByteArray olarak dinamik bir resim sağlayın.

Kotlin

override fun onTileResourcesRequest(
    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> onTileResourcesRequest(
       @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()
);
}