با کاشی شروع کنید

برای شروع ارائه کاشی ها از برنامه خود، وابستگی های زیر را در فایل build.gradle برنامه خود قرار دهید.

شیار

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

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

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

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

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

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

کاتلین

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

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

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

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

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

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

یک کاشی ایجاد کنید

برای ارائه یک کاشی از برنامه خود، کلاسی ایجاد کنید که TileService را گسترش دهد و متدها را اجرا کند، همانطور که در نمونه کد زیر نشان داده شده است:

کاتلین

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

جاوا

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

سپس، یک سرویس در داخل تگ <application> فایل AndroidManifest.xml خود اضافه کنید.

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

فیلتر مجوز و هدف این سرویس را به عنوان ارائه‌دهنده کاشی ثبت می‌کند.

هنگام پیکربندی کاشی‌ها روی تلفن یا ساعت خود، نماد، برچسب و توضیحات به کاربر نشان داده می‌شود.

از تگ ابرداده پیش‌نمایش برای نمایش پیش‌نمایش کاشی هنگام پیکربندی آن در تلفن خود استفاده کنید.

مروری بر چرخه عمر سرویس کاشی

هنگامی که TileService خود را در مانیفست برنامه خود ایجاد و اعلام کردید، می توانید به تغییرات وضعیت سرویس کاشی پاسخ دهید.

TileService یک سرویس محدود است. TileService شما در نتیجه درخواست برنامه شما یا اگر سیستم نیاز به برقراری ارتباط با آن داشته باشد، محدود می شود. یک چرخه عمر سرویس باند معمولی شامل چهار روش پاسخ به تماس زیر است: onCreate() , onBind() , onUnbind() و onDestroy() . سیستم هر بار که سرویس وارد مرحله چرخه حیات جدید می شود این روش ها را فراخوانی می کند.

علاوه بر تماس‌هایی که چرخه عمر سرویس محدود را کنترل می‌کنند، می‌توانید روش‌های دیگری را که مخصوص چرخه عمر TileService هستند پیاده‌سازی کنید. همه سرویس‌های کاشی باید onTileRequest() و onTileResourcesRequest() برای پاسخ به درخواست‌های به‌روزرسانی از سیستم پیاده‌سازی کنند.

  • onTileAddEvent() : سیستم این متد را فقط زمانی فراخوانی می کند که کاربر کاشی شما را برای اولین بار اضافه کند و اگر کاربر کاشی شما را حذف کرده و دوباره اضافه کند. این بهترین زمان برای انجام هر مقدار اولیه یک بار است.

    onTileAddEvent() فقط زمانی فراخوانی می شود که مجموعه کاشی ها مجدداً پیکربندی شوند، نه زمانی که یک کاشی توسط سیستم ایجاد شود. برای مثال، هنگامی که دستگاه راه‌اندازی مجدد یا روشن می‌شود، onTileAddEvent() برای کاشی‌هایی که قبلاً اضافه شده بودند فراخوانی نمی‌شود. به جای آن می توانید از getActiveTilesAsync() استفاده کنید تا یک عکس فوری از اینکه کدام کاشی های متعلق به شما فعال هستند را دریافت کنید.

  • onTileRemoveEvent() : سیستم این متد را فقط در صورتی فراخوانی می کند که کاربر کاشی شما را حذف کند.

  • onTileEnterEvent() : سیستم زمانی این روش را فراخوانی می کند که کاشی ارائه شده توسط این ارائه دهنده روی صفحه نمایش داده شود.

  • onTileLeaveEvent() : سیستم زمانی این روش را فراخوانی می کند که کاشی ارائه شده توسط این ارائه دهنده از روی صفحه نمایش خارج شود.

  • onTileRequest() : سیستم زمانی این متد را فراخوانی می کند که سیستم یک جدول زمانی جدید از این ارائه دهنده درخواست کند.

  • onTileResourcesRequest() : سیستم زمانی این متد را فراخوانی می کند که سیستم یک بسته منبع از این ارائه دهنده درخواست کند. این می تواند در اولین باری که یک کاشی بارگذاری می شود یا هر زمان که نسخه منبع تغییر می کند اتفاق بیفتد.

جستجو کنید کدام کاشی‌ها فعال هستند

کاشی های فعال کاشی هایی هستند که برای نمایش در ساعت اضافه شده اند. از روش استاتیک getActiveTilesAsync() TileService برای پرس و جو اینکه کدام کاشی های متعلق به برنامه شما فعال هستند استفاده کنید.

ایجاد رابط کاربری برای کاشی ها

طرح یک کاشی با استفاده از الگوی سازنده نوشته شده است. طرح کاشی مانند درختی ساخته می شود که از ظروف چیدمان و عناصر اصلی چیدمان تشکیل شده است. هر عنصر layout دارای ویژگی هایی است که می توانید از طریق روش های مختلف تنظیم کننده آن ها را تنظیم کنید.

عناصر چیدمان اولیه

عناصر بصری زیر از کتابخانه protolayout به همراه اجزای Material پشتیبانی می شوند:

  • Text : رشته ای از متن را ارائه می دهد که به صورت اختیاری بسته بندی می شود.
  • Image : یک تصویر را ارائه می دهد.
  • Spacer : بالشتک بین عناصر را فراهم می کند یا زمانی که رنگ پس زمینه آن را تنظیم می کنید می تواند به عنوان یک تقسیم کننده عمل کند.

اجزای مواد

علاوه بر عناصر اساسی، کتابخانه protolayout-material اجزایی را ارائه می‌کند که طراحی کاشی را مطابق با توصیه‌های رابط کاربر طراحی متریال تضمین می‌کند.

  • Button : جزء دایره ای قابل کلیک طراحی شده برای حاوی یک نماد.
  • Chip : مولفه‌ای به شکل استادیوم قابل کلیک که حاوی حداکثر دو خط متن و یک نماد اختیاری است.

  • CompactChip : مولفه استادیوم شکل قابل کلیک که حاوی یک خط متن است.

  • TitleChip : مولفه‌ای به شکل استادیوم قابل کلیک شبیه به Chip اما با ارتفاع بیشتر برای قرار دادن متن عنوان.

  • CircularProgressIndicator : نشانگر پیشرفت دایره ای است که می تواند در داخل یک EdgeContentLayout قرار گیرد تا پیشرفت را در اطراف لبه های صفحه نمایش دهد.

ظروف چیدمان

کانتینرهای زیر به همراه طرح‌بندی مواد پشتیبانی می‌شوند:

  • Row : عناصر کودک را یکی پس از دیگری به صورت افقی قرار می دهد.
  • Column : عناصر کودک را یکی پس از دیگری به صورت عمودی قرار می دهد.
  • Box : عناصر کودک را روی هم می‌پوشاند.
  • Arc : عناصر کودک را در یک دایره قرار می دهد.
  • Spannable : FontStyles خاص را به بخش هایی از متن به همراه متن و تصاویر در هم می زند. برای اطلاعات بیشتر، به Spannables مراجعه کنید.

هر ظرف می تواند حاوی یک یا چند کودک باشد که خود آنها نیز می توانند ظرف باشند. به عنوان مثال، یک Column می تواند چندین عنصر Row را در کودکی داشته باشد و در نتیجه یک طرح شبکه مانند ایجاد کند.

به عنوان مثال، یک کاشی با یک طرح بندی ظرف و دو عنصر طرح بندی فرزند می تواند به شکل زیر باشد:

کاتلین

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

جاوا

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

چیدمان مواد

علاوه بر طرح‌بندی‌های اولیه، کتابخانه protolayout-material چند طرح‌بندی نظری ارائه می‌کند که برای نگهداری عناصر در «شاخ‌های» خاص ساخته شده‌اند.

  • PrimaryLayout : یک CompactChip اصلی را در پایین با محتوای متمرکز در بالای آن قرار می دهد.

  • MultiSlotLayout : برچسب‌های اولیه و ثانویه را با محتوای اختیاری در میان و یک CompactChip اختیاری در پایین قرار می‌دهد.

  • MultiButtonLayout : مجموعه‌ای از دکمه‌ها را که طبق دستورالعمل‌های Material مرتب شده‌اند، قرار می‌دهد.

  • EdgeContentLayout : محتوا را در لبه یک صفحه قرار می دهد، مانند CircularProgressIndicator . هنگام استفاده از این چیدمان، محتوای درون آن دارای حاشیه‌های مناسب است و به‌طور خودکار padding اعمال می‌شود.

قوس ها

کودکان ظرف Arc زیر پشتیبانی می شوند:

  • ArcLine : یک خط منحنی در اطراف Arc ارائه می دهد.
  • ArcText : متن منحنی را در Arc ارائه می دهد.
  • ArcAdapter : یک عنصر چیدمان اصلی را در کمان ارائه می دهد که مماس بر کمان کشیده شده است.

برای اطلاعات بیشتر، به مستندات مرجع برای هر یک از انواع عناصر مراجعه کنید.

اصلاح کننده ها

هر عنصر طرح بندی موجود می تواند به صورت اختیاری اصلاح کننده هایی روی آن اعمال شود. از این اصلاح کننده ها برای اهداف زیر استفاده کنید:

  • ظاهر بصری چیدمان را تغییر دهید. برای مثال، یک پس‌زمینه، حاشیه یا بالشتک به عنصر طرح‌بندی خود اضافه کنید.
  • ابرداده در مورد طرح بندی اضافه کنید. به عنوان مثال، برای استفاده در صفحه‌خوان‌ها، یک اصلاح‌کننده معنایی به عنصر طرح‌بندی خود اضافه کنید.
  • قابلیت اضافه کنید. به عنوان مثال، یک اصلاح کننده قابل کلیک به عنصر طرح خود اضافه کنید تا کاشی شما تعاملی شود. برای اطلاعات بیشتر، به تعامل با کاشی ها مراجعه کنید.

به عنوان مثال، می‌توانیم ظاهر و ابرداده پیش‌فرض یک Image را همانطور که در نمونه کد زیر نشان داده شده است، سفارشی کنیم:

کاتلین

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

جاوا

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

Spannable نوع خاصی از کانتینر است که عناصر را مشابه متن قرار می دهد. این زمانی مفید است که می خواهید یک سبک متفاوت را فقط برای یک زیر رشته در یک بلوک بزرگتر از متن اعمال کنید، چیزی که با عنصر Text امکان پذیر نیست.

ظرف Spannable با کودکان Span پر شده است. سایر کودکان یا نمونه‌های تودرتو Spannable مجاز نیستند.

دو نوع بچه Span وجود دارد:

  • SpanText : متن را با یک سبک خاص ارائه می دهد.
  • SpanImage : یک تصویر را با متن ارائه می دهد.

به عنوان مثال، می‌توانید «world» را در کاشی «Hello world» به صورت مورب درج کنید و تصویری را بین کلمات وارد کنید، همانطور که در نمونه کد زیر نشان داده شده است:

کاتلین

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

جاوا

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

با منابع کار کنید

کاشی ها به هیچ یک از منابع برنامه شما دسترسی ندارند. این به این معنی است که نمی‌توانید شناسه تصویر اندروید را به عنصر طرح‌بندی Image ارسال کنید و انتظار داشته باشید که برطرف شود. در عوض، متد onTileResourcesRequest() نادیده بگیرید و هر منبعی را به صورت دستی ارائه کنید.

دو راه برای ارائه تصاویر در متد onTileResourcesRequest() وجود دارد:

کاتلین

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

جاوا

@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()
);
}
{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}