نسخه سازی کاشی ها

در دستگاه‌های Wear OS، کاشی‌ها توسط دو جزء کلیدی با نسخه‌بندی مستقل رندر می‌شوند. برای کمک به عملکرد صحیح کاشی‌های برنامه شما در تمام دستگاه‌ها، درک این معماری اساسی مهم است.

  • کتابخانه‌های مرتبط با کاشی Jetpack : این کتابخانه‌ها (از جمله Wear Tiles و Wear ProtoLayout) در برنامه شما تعبیه شده‌اند و شما، به عنوان توسعه‌دهنده، نسخه‌های آنها را کنترل می‌کنید. برنامه شما از این کتابخانه‌ها برای ساخت یک شیء TileBuilder.Tile (ساختار داده‌ای که کاشی شما را نشان می‌دهد) در پاسخ به فراخوانی onTileRequest() سیستم استفاده می‌کند.
  • رندرکننده‌ی ProtoLayout: این مؤلفه‌ی سیستمی مسئول رندر کردن شیء Tile روی صفحه نمایش و مدیریت تعاملات کاربر است. نسخه‌ی رندرکننده توسط توسعه‌دهنده‌ی برنامه کنترل نمی‌شود و می‌تواند در دستگاه‌های مختلف، حتی دستگاه‌هایی با سخت‌افزار یکسان، متفاوت باشد.

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

این سند توضیح می‌دهد که چگونه برنامه خود را با نسخه‌های مختلف کتابخانه Tiles و ProtoLayout Renderer سازگار کنید. همچنین نحوه مهاجرت به نسخه‌های بالاتر کتابخانه Jetpack را شرح می‌دهد.

سازگاری را در نظر بگیرید

برای ایجاد یک Tile که به درستی در طیف وسیعی از دستگاه‌ها کار کند، پشتیبانی از ویژگی‌های مختلف را در نظر بگیرید. می‌توانید این کار را از طریق دو استراتژی اصلی انجام دهید: تشخیص قابلیت‌های رندرکننده در زمان اجرا و ارائه fallbackهای داخلی.

تشخیص قابلیت‌های رندرکننده

شما می‌توانید طرح‌بندی کاشی خود را بر اساس ویژگی‌های موجود در یک دستگاه خاص، به صورت پویا تغییر دهید.

تشخیص نسخه رندرکننده

  • از متد getRendererSchemaVersion() از شیء DeviceParameters که به متد onTileRequest() شما ارسال شده است، استفاده کنید. این متد شماره نسخه‌های اصلی و فرعی رندرکننده ProtoLayout روی دستگاه را برمی‌گرداند.
  • سپس می‌توانید از منطق شرطی در پیاده‌سازی onTileRequest() خود برای تطبیق طراحی یا رفتار Tile خود بر اساس نسخه رندرکننده شناسایی‌شده استفاده کنید.

حاشیه‌نویسی @RequiresSchemaVersion

  • حاشیه‌نویسی @RequiresSchemaVersion در متدهای ProtoLayout، حداقل نسخه طرحواره رندر مورد نیاز برای آن متد را نشان می‌دهد تا مطابق مستندات ( مثال ) عمل کند.
    • اگرچه فراخوانی متدی که به نسخه رندرکننده بالاتری نسبت به نسخه موجود در دستگاه نیاز دارد، باعث خرابی برنامه شما نمی‌شود، اما می‌تواند منجر به عدم نمایش محتوا یا نادیده گرفتن ویژگی شود.

مثالی از تشخیص نسخه

val rendererVersion = requestParams.deviceConfiguration.rendererSchemaVersion

val arcElement =
    // DashedArcLine has the annotation @RequiresSchemaVersion(major = 1, minor = 500)
    // and so is supported by renderer versions 1.500 and greater
    if (
        rendererVersion.major > 1 ||
        (rendererVersion.major == 1 && rendererVersion.minor >= 500)
    ) {
        // Use DashedArcLine if the renderer supports it …
        DashedArcLine.Builder()
            .setLength(degrees(270f))
            .setThickness(8f)
            .setLinePattern(
                LayoutElementBuilders.DashedLinePattern.Builder()
                    .setGapSize(8f)
                    .setGapInterval(10f)
                    .build()
            )
            .build()
    } else {
        // … otherwise use ArcLine.
        ArcLine.Builder().setLength(degrees(270f)).setThickness(dp(8f)).build()
    }

ارائه راه‌حل‌های جایگزین

برخی منابع به شما امکان می‌دهند که یک نسخه پشتیبان (fallback) را مستقیماً در سازنده تعریف کنید. این کار اغلب ساده‌تر از بررسی نسخه رندرکننده است و در صورت وجود، رویکرد ترجیحی است.

یک مورد استفاده رایج، ارائه یک تصویر ثابت به عنوان جایگزین برای انیمیشن Lottie است. اگر دستگاه از انیمیشن‌های Lottie پشتیبانی نکند، به جای آن تصویر ثابت را رندر می‌کند.

val lottieImage =
    ResourceBuilders.ImageResource.Builder()
        .setAndroidLottieResourceByResId(
            ResourceBuilders.AndroidLottieResourceByResId.Builder(R.raw.lottie)
                .setStartTrigger(createOnVisibleTrigger())
                .build()
        )
        // Fallback if lottie is not supported
        .setAndroidResourceByResId(
            ResourceBuilders.AndroidImageResourceByResId.Builder()
                .setResourceId(R.drawable.lottie_fallback)
                .build()
        )
        .build()

با نسخه‌های مختلف رندرکننده تست کنید

برای آزمایش کاشی‌های خود در برابر نسخه‌های مختلف رندرکننده، آنها را در نسخه‌های مختلف شبیه‌ساز Wear OS مستقر کنید. (در دستگاه‌های فیزیکی، به‌روزرسانی‌های رندرکننده ProtoLayout توسط فروشگاه Play یا به‌روزرسانی‌های سیستم ارائه می‌شوند. نصب اجباری یک نسخه رندرکننده خاص امکان‌پذیر نیست.)

قابلیت پیش‌نمایش کاشی‌ها (Tile Preview) اندروید استودیو از یک رندرکننده (renderer) تعبیه‌شده در کتابخانه Jetpack ProtoLayout که کد شما به آن وابسته است، استفاده می‌کند، بنابراین رویکرد دیگر این است که هنگام آزمایش کاشی‌ها (tiles)، به نسخه‌های مختلف کتابخانه Jetpack وابسته باشید.

مهاجرت به Tiles 1.5 / ProtoLayout 1.3 (Material 3 Expressive)

کتابخانه‌های کاشی Jetpack خود را به‌روزرسانی کنید تا از جدیدترین پیشرفت‌ها، از جمله تغییرات رابط کاربری، بهره‌مند شوید تا کاشی‌های شما به طور یکپارچه با سیستم ادغام شوند.

Jetpack Tiles 1.5 و Jetpack ProtoLayout 1.3 چندین بهبود و تغییر قابل توجه را معرفی می‌کنند. این موارد عبارتند از:

  • یک API شبیه به Compose برای توصیف رابط کاربری.
  • اجزای رسا و جذاب متریال ۳ ، شامل دکمه‌ی لبه‌ی پایینی و پشتیبانی از جلوه‌های بصری بهبود یافته: انیمیشن‌های Lottie، انواع گرادیان بیشتر و سبک‌های جدید خطوط قوسی. - توجه: برخی از این ویژگی‌ها را می‌توان بدون مهاجرت به API جدید نیز استفاده کرد.

توصیه‌ها

هنگام انتقال کاشی‌هایتان، این توصیه‌ها را دنبال کنید:

  • تمام کاشی‌های خود را به‌طور همزمان منتقل کنید. از ترکیب نسخه‌های کاشی‌ها در برنامه خود خودداری کنید. در حالی که اجزای Material 3 در یک مصنوع جداگانه ( androidx.wear.protolayout:protolayout-material3 ) قرار دارند - که از نظر فنی امکان استفاده از کاشی‌های M2.5 و M3 را در یک برنامه واحد فراهم می‌کند - ما اکیداً توصیه می‌کنیم از این رویکرد خودداری کنید، مگر اینکه کاملاً ضروری باشد (به عنوان مثال، اگر برنامه شما تعداد زیادی کاشی دارد که نمی‌توان همه آنها را به‌طور همزمان منتقل کرد).
  • با توجه به ماهیت بسیار ساختاریافته و قالب‌بندی‌شده‌ی کاشی‌ها ، از طرح‌های موجود در نمونه‌های موجود به عنوان نقطه شروع برای طرح‌های خود استفاده کنید.
  • روی انواع صفحه نمایش و اندازه فونت‌ها آزمایش کنید. کاشی‌ها اغلب اطلاعات زیادی دارند و متن (به‌خصوص وقتی روی دکمه‌ها قرار می‌گیرد) مستعد سرریز و بریده شدن است. برای به حداقل رساندن این مشکل، از اجزای از پیش ساخته شده استفاده کنید و از سفارشی‌سازی گسترده خودداری کنید. با استفاده از ویژگی پیش‌نمایش کاشی اندروید استودیو و همچنین روی چندین دستگاه واقعی آزمایش کنید.

فرآیند مهاجرت

برای انتقال کاشی‌های خود، این مراحل را دنبال کنید:

به‌روزرسانی وابستگی‌ها

ابتدا، فایل build.gradle.kts خود را به‌روزرسانی کنید. نسخه‌ها را به‌روزرسانی کنید و وابستگی protolayout-material را به protolayout-material3 تغییر دهید، همانطور که نشان داده شده است:

// In build.gradle.kts

//val tilesVersion = "1.4.1"
//val protoLayoutVersion = "1.2.1"

// Use these versions for M3.
val tilesVersion = "1.5.0"
val protoLayoutVersion = "1.3.0"

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

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

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

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

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

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

TileService تا حد زیادی بدون تغییر باقی مانده است

تغییرات اولیه در این مهاجرت بر اجزای رابط کاربری تأثیر می‌گذارند. در نتیجه، پیاده‌سازی TileService شما، شامل هرگونه مکانیسم بارگذاری منابع، باید به حداقل یا بدون تغییر نیاز داشته باشد.

استثنای اصلی شامل ردیابی فعالیت کاشی‌ها می‌شود: اگر برنامه شما از onTileEnterEvent() یا onTileLeaveEvent() استفاده می‌کند، توصیه می‌کنیم به onRecentInteractionEventsAsync() مهاجرت کنید. از API 36 به بعد، این رویدادها دسته‌ای می‌شوند.

کد تولید طرح‌بندی خود را تطبیق دهید

در ProtoLayout 1.2 (M2.5)، متد onTileRequest() یک TileBuilders.Tile برمی‌گرداند. این شیء شامل عناصر مختلفی از جمله TimelineBuilders.Timeline بود که به نوبه خود LayoutElement توصیف‌کننده رابط کاربری کاشی را در خود جای داده بود.

با ProtoLayout 1.3 (M3)، در حالی که ساختار و جریان کلی داده‌ها تغییر نکرده است، LayoutElement اکنون با استفاده از رویکردی الهام گرفته از Compose با چیدمانی مبتنی بر اسلات‌های تعریف‌شده ساخته می‌شود که (از بالا به پایین) titleSlot (اختیاری؛ معمولاً برای عنوان یا سربرگ اصلی)، mainSlot (اجباری؛ برای محتوای اصلی) و bottomSlot (اختیاری؛ اغلب برای اقداماتی مانند دکمه لبه یا اطلاعات تکمیلی مانند متن کوتاه) هستند. این چیدمان توسط تابع primaryLayout() ساخته می‌شود.

طرح‌بندی یک کاشی که mainSlot، titleSlot و bottomSlot را نشان می‌دهد
شکل ۱.: شیارهای یک کاشی.
مقایسه توابع طرح‌بندی M2.5 و M3

M2.5

fun myLayout(
    context: Context,
    deviceConfiguration: DeviceParametersBuilders.DeviceParameters
) =
    PrimaryLayout.Builder(deviceConfiguration)
        .setResponsiveContentInsetEnabled(true)
        .setContent(
            Text.Builder(context, "Hello World!")
                .setTypography(Typography.TYPOGRAPHY_BODY1)
                .build()
        )
        .build()

ام۳

fun myLayout(
    context: Context,
    deviceConfiguration: DeviceParametersBuilders.DeviceParameters,
) =
    materialScope(context, deviceConfiguration) {
        primaryLayout(mainSlot = { text("Hello, World!".layoutString) })
    }

برای برجسته کردن تفاوت‌های کلیدی:

  1. حذف سازنده‌ها . الگوی سازنده قبلی برای کامپوننت‌های رابط کاربری متریال با یک سینتکس الهام گرفته از Compose و با بیانی‌تر جایگزین شده است. (کامپوننت‌های غیر رابط کاربری مانند String/Color/Modifiers نیز پوشش‌های جدید Kotlin را دریافت می‌کنند.)
  2. توابع مقداردهی اولیه و طرح‌بندی استاندارد . طرح‌بندی‌های M3 به توابع مقداردهی اولیه و ساختار استاندارد متکی هستند: materialScope() و primaryLayout() . این توابع اجباری محیط M3 (قالب‌بندی، محدوده کامپوننت با استفاده از materialScope ) را مقداردهی اولیه می‌کنند و طرح‌بندی مبتنی بر اسلات اصلی (با استفاده از primaryLayout ) را تعریف می‌کنند. هر دو باید دقیقاً یک بار در هر طرح‌بندی فراخوانی شوند.

قالب‌بندی

متریال ۳ چندین تغییر در تم‌بندی ارائه می‌دهد، از جمله رنگ پویا و مجموعه‌ای گسترده از گزینه‌های تایپوگرافی و شکل.

رنگ

یکی از ویژگی‌های برجسته‌ی Material 3 Expressive «قالب‌بندی پویا» است: کاشی‌هایی که این ویژگی را فعال می‌کنند (به‌طور پیش‌فرض فعال هستند) در قالب ارائه‌شده توسط سیستم نمایش داده می‌شوند (در دسترس بودن آن به دستگاه و پیکربندی کاربر بستگی دارد).

تغییر دیگر در M3، افزایش تعداد توکن‌های رنگی است که از ۴ به ۲۹ افزایش یافته است. توکن‌های رنگی جدید را می‌توان در کلاس ColorScheme یافت.

تایپوگرافی

مشابه M2.5، M3 به شدت به ثابت‌های اندازه فونت از پیش تعریف‌شده متکی است - تعیین مستقیم اندازه فونت توصیه نمی‌شود. این ثابت‌ها در کلاس Typography قرار دارند و طیف نسبتاً گسترده‌ای از گزینه‌های رساتر را ارائه می‌دهند.

برای جزئیات کامل، به مستندات تایپوگرافی مراجعه کنید.

شکل

بیشتر اجزای M3 می‌توانند از نظر شکل و همچنین رنگ، ابعاد متفاوتی داشته باشند.

یک textButton (در mainSlot ) با شکل full :

کاشی با شکل «کامل» (گوشه‌های گردتر)
شکل ۲. کاشی با شکل «کامل»

همان دکمه متنی با شکل small :

کاشی با شکل «کوچک» (گوشه‌های کمتر گرد)
شکل ۳. کاشی با شکل «کوچک»

قطعات

اجزای M3 نسبت به همتایان M2.5 خود انعطاف‌پذیرتر و قابل تنظیم‌تر هستند. M2.5 اغلب برای پردازش‌های بصری متنوع به اجزای متمایزی نیاز داشت، در حالی که M3 اغلب از یک جزء پایه عمومی و بسیار قابل تنظیم با پیش‌فرض‌های خوب استفاده می‌کند.

این اصل در مورد طرح‌بندی ریشه نیز صدق می‌کند. در M2.5، این طرح‌بندی یا PrimaryLayout بود یا EdgeContentLayout . در M3، پس از ایجاد یک MaterialScope سطح بالا، تابع primaryLayout() را فراخوانی می‌کنید. این تابع طرح‌بندی ریشه را مستقیماً برمی‌گرداند - بدون نیاز به سازنده‌ها - و LayoutElements برای چندین اسلات، مانند titleSlot ، mainSlot و bottomSlot می‌پذیرد. می‌توانید این اسلات‌ها را با اجزای رابط کاربری ملموس - مانند آنهایی که توسط text() ، button() یا card() برگردانده می‌شوند - یا با ساختارهای طرح‌بندی، مانند Row یا Column از LayoutElementBuilders پر کنید.

تم‌ها یکی دیگر از پیشرفت‌های کلیدی M3 هستند. به طور پیش‌فرض، عناصر رابط کاربری به طور خودکار از مشخصات ظاهری M3 پیروی می‌کنند و از تم‌بندی پویا پشتیبانی می‌کنند.

M2.5 ام۳
عناصر تعاملی
Button یا Chip
متن
Text text()
شاخص‌های پیشرفت
CircularProgressIndicator circularProgressIndicator() یا segmentedCircularProgressIndicator()
طرح بندی
PrimaryLayout یا EdgeContentLayout primaryLayout()
buttonGroup()
تصاویر
icon() ، avatarImage() یا backgroundImage()

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

در M3، Modifiers که برای تزئین یا تقویت یک کامپوننت استفاده می‌کنید، بیشتر شبیه Compose هستند. این تغییر می‌تواند با ساخت خودکار انواع داخلی مناسب، کدهای تکراری را کاهش دهد. (این تغییر متعامد با استفاده از کامپوننت‌های رابط کاربری M3 است؛ در صورت لزوم، می‌توانید از اصلاح‌کننده‌های سبک سازنده از ProtoLayout 1.2 با کامپوننت‌های رابط کاربری M3 استفاده کنید و برعکس.)

M2.5

// Uses Builder-style modifier to set opacity
fun myModifier(): ModifiersBuilders.Modifiers =
    ModifiersBuilders.Modifiers.Builder()
        .setOpacity(TypeBuilders.FloatProp.Builder(0.5F).build())
        .build()

ام۳

// Uses Compose-like modifiers to set opacity
fun myModifier(): LayoutModifier = LayoutModifier.opacity(0.5F)

شما می‌توانید با استفاده از هر دو سبک API، اصلاح‌کننده‌ها را بسازید، و همچنین می‌توانید از تابع افزونه toProtoLayoutModifiers() برای تبدیل یک LayoutModifier به یک ModifiersBuilders.Modifier استفاده کنید.

توابع کمکی

در حالی که ProtoLayout 1.3 به بسیاری از اجزای رابط کاربری اجازه می‌دهد تا با استفاده از یک API الهام گرفته از Compose بیان شوند، عناصر طرح‌بندی اساسی مانند ردیف‌ها و ستون‌ها از LayoutElementBuilders همچنان از الگوی سازنده استفاده می‌کنند. برای پر کردن این شکاف سبکی و ارتقای سازگاری با APIهای جدید اجزای M3، استفاده از توابع کمکی را در نظر بگیرید.

بدون یاران

primaryLayout(
    mainSlot = {
        Column.Builder()
            .setWidth(expand())
            .setHeight(expand())
            .addContent(text("A".layoutString))
            .addContent(text("B".layoutString))
            .addContent(text("C".layoutString))
            .build()
    }
)

با کمک‌کنندگان

// Function literal with receiver helper function
fun column(builder: Column.Builder.() -> Unit) =
    Column.Builder().apply(builder).build()

primaryLayout(
    mainSlot = {
        column {
            setWidth(expand())
            setHeight(expand())
            addContent(text("A".layoutString))
            addContent(text("B".layoutString))
            addContent(text("C".layoutString))
        }
    }
)

مهاجرت به Tiles 1.2 / ProtoLayout 1.0

از نسخه ۱.۲ به بعد، اکثر APIهای طرح‌بندی Tiles در فضای نام androidx.wear.protolayout قرار دارند. برای استفاده از جدیدترین APIها، مراحل مهاجرت زیر را در کد خود انجام دهید.

به‌روزرسانی وابستگی‌ها

در فایل ساخت ماژول برنامه خود، تغییرات زیر را اعمال کنید:

گرووی

  // Remove
  implementation 'androidx.wear.tiles:tiles-material:version'

  // Include additional dependencies
  implementation "androidx.wear.protolayout:protolayout:1.3.0"
  implementation "androidx.wear.protolayout:protolayout-material:1.3.0"
  implementation "androidx.wear.protolayout:protolayout-expression:1.3.0"

  // Update
  implementation "androidx.wear.tiles:tiles:1.5.0"

کاتلین

  // Remove
  implementation("androidx.wear.tiles:tiles-material:version")

  // Include additional dependencies
  implementation("androidx.wear.protolayout:protolayout:1.3.0")
  implementation("androidx.wear.protolayout:protolayout-material:1.3.0")
  implementation("androidx.wear.protolayout:protolayout-expression:1.3.0")

  // Update
  implementation("androidx.wear.tiles:tiles:1.5.0")

به‌روزرسانی فضاهای نام

در فایل‌های کد مبتنی بر کاتلین و جاوای برنامه‌تان، به‌روزرسانی‌های زیر را انجام دهید: به‌طور جایگزین، می‌توانید این اسکریپت تغییر نام فضای نام را اجرا کنید.

  1. تمام ایمپورت‌های androidx.wear.tiles.material.* را با androidx.wear.protolayout.material.* جایگزین کنید. این مرحله را برای کتابخانه androidx.wear.tiles.material.layouts نیز انجام دهید.
  2. بیشتر ایمپورت‌های androidx.wear.tiles.* دیگر را با androidx.wear.protolayout.* جایگزین کنید.

    ایمپورت‌های مربوط به androidx.wear.tiles.EventBuilders ، androidx.wear.tiles.RequestBuilders ، androidx.wear.tiles.TileBuilders و androidx.wear.tiles.TileService باید به همان شکل باقی بمانند.

  3. چند متد منسوخ شده از کلاس‌های TileService و TileBuilder را تغییر نام دهید:

    1. TileBuilders : getTimeline() برای getTileTimeline() و setTimeline() برای setTileTimeline()
    2. TileService : onResourcesRequest() به onTileResourcesRequest()
    3. RequestBuilders.TileRequest : getDeviceParameters() برای getDeviceConfiguration() ، setDeviceParameters() برای setDeviceConfiguration() ، getState() برای getCurrentState() و setState() برای setCurrentState()