على أجهزة Wear OS، يتم عرض المربّعات من خلال مكوّنين رئيسيَّين بإصدارين مستقلَّين. لضمان عمل مربّعات التطبيقات بشكل صحيح على جميع الأجهزة، من المهم فهم هذه البنية الأساسية.
- المكتبات ذات الصلة بتطبيق Jetpack Tiles: يتم تضمين هذه المكتبات (بما في ذلك Wear Tiles
وWear ProtoLayout) في تطبيقك، ويكون بإمكانك بصفتك المطوّر
التحكّم في إصداراتها. يستخدم تطبيقك هذه المكتبات لإنشاء عنصر
TileBuilder.Tile
(بنية البيانات التي تمثّل مربّع معلوماتك) استجابةً لطلبonTileRequest()
من النظام. - ProtoLayout Renderer: يُعدّ مكوّن النظام هذا مسؤولاً عن عرض
العنصر
Tile
على الشاشة ومعالجة تفاعلات المستخدم. لا يتحكّم مطوّر التطبيقات في إصدار معالج العرض، ويمكن أن يختلف الإصدار من جهاز لآخر، حتى إذا كانت الأجهزة تتضمّن أجهزة مشابهة.
يمكن أن يختلف مظهر مربّع البيانات أو سلوكه استنادًا إلى إصدارَي مكتبة Jetpack Tiles وProtoLayout Renderer في تطبيقك على جهاز المستخدم. على سبيل المثال، قد يتيح أحد الأجهزة التدوير أو عرض بيانات معدل ضربات القلب، بينما قد لا يتيح ذلك الجهاز الآخر.
يوضّح هذا المستند كيفية التأكّد من توافق تطبيقك مع إصدارات مختلفة من مكتبة Tiles وProtoLayout Renderer، وكيفية نقل البيانات إلى إصدارات أحدث من مكتبة Jetpack.
مراعاة التوافق
لإنشاء مربّع يعمل بشكل صحيح على مجموعة من الأجهزة، يجب مراعاة ما يلي:
رصد إصدار أداة التحويل
- استخدِم طريقة
getRendererSchemaVersion()
للكائنDeviceParameters
الذي تم تمريره إلى طريقة onTileRequest(). تعرض هذه الطريقة رقمَي الإصدار الرئيسي والثانوي لواجهة ProtoLayout Renderer على الجهاز. - يمكنك بعد ذلك استخدام المنطق الشَرطي في عملية تنفيذ
onTileRequest()
لتكييف تصميم مربّع معلوماتك أو سلوكه استنادًا إلى إصدار مُنشئ العرض المُكتشَف.- على سبيل المثال، إذا لم تكن صورة متحركة معيّنة متوافقة، يمكنك عرض صورة ثابتة بدلاً منها.
التعليق التوضيحي @RequiresSchemaVersion
- يشير التعليق التوضيحي
@RequiresSchemaVersion
في طرق ProtoLayout إلى الحد الأدنى لإصدار مخطّط أداة العرض المطلوب لكي تعمل هذه الطريقة على النحو المُسجَّل (مثال).- على الرغم من أنّ استدعاء طريقة تتطلّب إصدارًا أعلى من أداة التحويل من مثبّت على الجهاز لن يؤدي إلى تعطُّل تطبيقك، إلا أنّه قد يؤدي إلى عدم عرض المحتوى أو تجاهل الميزة.
مثال
override fun onTileRequest(
requestParams: TileService.TileRequest
): ListenableFuture<Tile> {
val rendererVersion =
requestParams.deviceConfiguration.rendererSchemaVersion
val tile = Tile.Builder()
if (
rendererVersion.major > 1 ||
(rendererVersion.major == 1 && rendererVersion.minor >= 300)
) {
// Use a feature supported in renderer version 1.300 or later
tile.setTileTimeline(/* ... */ )
} else {
// Provide fallback content for older renderers
tile.setTileTimeline(/* ... */ )
}
return Futures.immediateFuture(tile.build())
}
الاختبار باستخدام إصدارات مختلفة من مُعِدِّل العرض
لاختبار مربّعاتك على إصدارات مختلفة من أداة عرض الرسومات، يمكنك نشرها على إصدارات مختلفة من محاكي Wear OS. (على الأجهزة الفعلية، يتم من خلال "متجر Play" أو تحديثات النظام إرسال تحديثات أداة ProtoLayout Renderer. ولا يمكن فرض تثبيت إصدار معيّن من مُعِدِّل العرض.)
تستخدِم ميزة "معاينة مربّعات البيانات" في Android Studio أداة عرض مضمّنة في مكتبة Jetpack ProtoLayout التي يعتمد عليها الرمز البرمجي، لذا يمكنك استخدام نهج آخر وهو الاعتماد على إصدارات مختلفة من مكتبة Jetpack عند اختبار مربّعات البيانات.
نقل البيانات إلى Tiles 1.5 / ProtoLayout 1.3 (Material 3 Expressive)
يمكنك تحديث مكتبات Jetpack Tile للاستفادة من أحدث التحسينات، بما في ذلك تغييرات واجهة المستخدم لدمج وحداتك بسلاسة مع النظام.
يقدّم الإصدار 1.5 من Jetpack Tiles والإصدار 1.3 من Jetpack ProtoLayout العديد من التحسينات والتغييرات البارزة. ومن بينها:
- واجهة برمجة تطبيقات مشابهة لواجهة Compose لوصف واجهة المستخدم
- مكوّنات Material 3 Expressive، بما في ذلك زر الالتفاف على الحافة وتوفّر مرئيات محسّنة: صور متحركة من Lottie ومزيد من أنواع التدرّج وأنماط جديدة لخطوط القوس - ملاحظة: يمكن أيضًا استخدام بعض هذه الميزات بدون نقل البيانات إلى واجهة برمجة التطبيقات الجديدة.
الاقتراحات
- نقل جميع مربّعات البيانات في الوقت نفسه: تجنَّب خلط إصدارات مربّعات الشاشة
داخل تطبيقك. على الرغم من أنّ مكوّنات Material 3 تقع في ملف رمز مميّز (
androidx.wear.protolayout:protolayout-material3
) منفصل، ما يجعله من الناحية الفنية ممكنًا استخدام مربّعات الشاشة لكل من M2.5 وM3 في التطبيق نفسه، ننصح بشدة بعدم اتّباع هذا النهج ما لم يكن ضروريًا تمامًا (مثلاً، إذا كان تطبيقك يتضمّن عددًا كبيرًا من مربّعات الشاشة لا يمكن نقلها بالكامل في آنٍ واحد). - اتّباع إرشادات تجربة المستخدم في ميزة "الألواح" نظرًا لطبيعة المكوّنات المصغّرة المنظَّمة للغاية والمستندة إلى نماذج، استخدِم التصميمات في عيّنات التطبيقات الحالية كنقاط بداية لتصميماتك.
- اختبِر التطبيق على مجموعة متنوعة من أحجام الشاشات والخطوط. غالبًا ما تكون المربّعات مكتظة بالمعلومات، ما يجعل النص (خاصةً عند وضعه على الأزرار) عرضة للامتلاء والاقتصاص. للحدّ من ذلك، استخدِم المكوّنات المُنشأة مسبقًا وتجنَّب التخصيص المكثّف. يمكنك إجراء الاختبار باستخدام ميزة معاينة مربّعات التطبيق في "استوديو Android"، بالإضافة إلى أجهزة حقيقية متعددة.
عملية نقل البيانات
تعديل العناصر التابعة
أولاً، عليك تعديل ملف 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-rc01"
val protoLayoutVersion = "1.3.0-rc01"
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()
. بدءًا من الإصدار 36 من واجهة برمجة التطبيقات، سيتم تجميع هذه الأحداث.
تعديل رمز إنشاء التنسيق
في ProtoLayout 1.2 (M2.5)، تُعيد الطريقة onTileRequest()
ملفًا بتنسيق
TileBuilders.Tile
. يحتوي هذا العنصر على عناصر مختلفة، بما في ذلك
TimelineBuilders.Timeline
، الذي يحتوي بدوره على LayoutElement
الذي يصف واجهة مستخدم مربّع الرموز.
مع استخدام ProtoLayout 1.3 (M3)، على الرغم من عدم
تغيُّر بنية البيانات وتدفقها بشكل عام، يتم الآن إنشاء LayoutElement
باستخدام أسلوب مستوحى من Compose
بتنسيق يستند إلى مَواضع محدّدة، وهي (من الأعلى إلى الأسفل)
titleSlot
(عادةً لعنوان أو رأس أساسي) وmainSlot
(للمحتوى الأساسي) وbottomSlot
(غالبًا لإجراءات مثل زر على الحافة أو
معلومات إضافية مثل نص قصير). يتم إنشاء هذا التنسيق باستخدام الدالة
primaryLayout()
.

مقارنة بين دالّتَي تنسيق 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)
.setColor(argb(0xFFFFFFFF.toInt()))
.build()
)
.build()
التصميم 3
fun myLayout(
context: Context,
deviceConfiguration: DeviceParametersBuilders.DeviceParameters,
) =
materialScope(context, deviceConfiguration) {
primaryLayout(mainSlot = { text("Hello, World!".layoutString) })
}
في ما يلي الاختلافات الرئيسية:
- استبعاد المقاولين: تم استبدال نمط المُنشئ التقليدي لمكوّنات واجهة مستخدم Material3 ببنية نحوية أكثر وضوحًا مستوحاة من Compose. (تحصل أيضًا المكونات غير المتعلّقة بواجهة المستخدم، مثل String/Color/Modifiers، على وحدات Kotlin التفافية الجديدة).
- وظائف الإعداد والتنسيق العادية تعتمد تنسيقات M3 على
وظائف الإعداد والبنية الموحّدة:
materialScope()
وprimaryLayout()
. تعمل هذه الدوالّ الإلزامية على بدء بيئة M3 (المظهر، ونطاق المكوّن من خلالmaterialScope
) وتحديد التنسيق الأساسي المستنِد إلى الفتحة (من خلالprimaryLayout
). ويجب استدعاء كلتا الدالتَين مرة واحدة فقط لكل تنسيق.
التصميم
اللون
من الميزات البارزة في Material 3 Expressive هي "المظاهر الديناميكية": سيتم عرض المكوّنات التي تفتعل هذه الميزة (تكون مفعّلة تلقائيًا) في المظهر الذي يقدّمه النظام (يعتمد مدى التوفّر على جهاز المستخدم وإعداداته).
ومن التغييرات الأخرى في الإصدار 3 من مخطّط الألوان توسيع نطاق عدد الرموز اللونية التي زادت
من 4 إلى 29. يمكن العثور على الرموز اللونية الجديدة في فئة
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
.
تمثّل المظاهر ميزة أخرى أساسية في الإصدار 3 من "إعلانات شبكة البحث". تلتزم عناصر واجهة المستخدم تلقائيًا بمواصفات تنسيق M3 وتتوافق مع المظاهر الديناميكية.
M2.5 | التصميم 3 |
---|---|
العناصر التفاعلية | |
Button أو Chip |
|
Text | |
Text |
text() |
مؤشرات التقدّم | |
CircularProgressIndicator |
circularProgressIndicator() أو segmentedCircularProgressIndicator() |
التصميم | |
PrimaryLayout أو EdgeContentLayout |
primaryLayout() |
— | buttonGroup() |
الصور | |
— | icon() أو avatarImage() أو backgroundImage() |
مفاتيح التعديل
في الإصدار M3، أصبحت Modifiers
، التي تستخدمها لتزيين مكوّن أو تحسينه،
أكثر شبهاً بـ Compose. يمكن أن يؤدي هذا التغيير إلى تقليل النماذج الجاهزة من خلال
إنشاء
الأنواع الداخلية المناسبة تلقائيًا. (هذا التغيير متوافق مع استخدام مكونات واجهة مستخدم M3، وإذا لزم الأمر، يمكنك استخدام عوامل التعديل بأسلوب أداة الإنشاء من ProtoLayout 1.2 مع مكونات واجهة مستخدم M3 والعكس صحيح).
M2.5
// A Builder-style modifier to set the opacity of an element to 0.5
fun myModifier(): ModifiersBuilders.Modifiers =
ModifiersBuilders.Modifiers.Builder()
.setOpacity(TypeBuilders.FloatProp.Builder(0.5F).build())
.build()
التصميم 3
// The equivalent Compose-like modifier is much simpler
fun myModifier(): LayoutModifier = LayoutModifier.opacity(0.5F)
يمكنك إنشاء عوامل تعديل باستخدام أي من أسلوبَي واجهة برمجة التطبيقات، ويمكنك أيضًا استخدام دالة الإضافة
toProtoLayoutModifiers()
لتحويل
LayoutModifier
إلى ModifiersBuilders.Modifier
.
الدوال المساعِدة
على الرغم من أنّ ProtoLayout 1.3 يسمح بالتعبير عن العديد من مكوّنات واجهة المستخدم باستخدام واجهة برمجة تطبيقات مستوحاة من Compose، فإنّ عناصر التنسيق الأساسية، مثل الصفوف و
الأعمدة من LayoutElementBuilders
، تستمر في استخدام أسلوب
الإنشاء. لسدّ هذه الفجوة في الأسلوب وتعزيز الاتساق مع
واجهات برمجة التطبيقات الجديدة لمكوّنات M3، ننصحك باستخدام الدوالّ المساعِدة.
بدون مساعدين
primaryLayout(
mainSlot = {
LayoutElementBuilders.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))
}
}
)
نقل البيانات إلى الإصدار 1.2 من Tiles أو الإصدار 1.0 من ProtoLayout
اعتبارًا من الإصدار 1.2، أصبحت معظم واجهات برمجة التطبيقات لتنسيق مربّعات المعلومات متوفّرة في مساحة الاسم androidx.wear.protolayout
. لاستخدام أحدث واجهات برمجة التطبيقات، أكمِل خطوات نقل البيانات التالية في
الرمز البرمجي.
تعديل العناصر التابعة
في ملف إنشاء وحدة التطبيق، أجرِ التغييرات التالية:
رائع
// Removeimplementation 'androidx.wear.tiles:tiles-material:version'// Include additional dependencies implementation "androidx.wear.protolayout:protolayout:1.2.1" implementation "androidx.wear.protolayout:protolayout-material:1.2.1" implementation "androidx.wear.protolayout:protolayout-expression:1.2.1" // Update implementation "androidx.wear.tiles:tiles:1.4.1"
Kotlin
// Removeimplementation("androidx.wear.tiles:tiles-material:version")// Include additional dependencies implementation("androidx.wear.protolayout:protolayout:1.2.1") implementation("androidx.wear.protolayout:protolayout-material:1.2.1") implementation("androidx.wear.protolayout:protolayout-expression:1.2.1") // Update implementation("androidx.wear.tiles:tiles:1.4.1")
تعديل مساحات الأسماء
في ملفات الرموز البرمجية المستندة إلى Kotlin وJava في تطبيقك، عليك إجراء التعديلات التالية. بدلاً من ذلك، يمكنك تنفيذ النص البرمجي لإعادة تسمية مساحة الاسم.
- استبدِل كل عمليات استيراد
androidx.wear.tiles.material.*
بعملياتandroidx.wear.protolayout.material.*
. أكمِل هذه الخطوة أيضًا لإضافة مكتبةandroidx.wear.tiles.material.layouts
. استبدِل معظم عمليات استيراد
androidx.wear.tiles.*
الأخرى باستخدامandroidx.wear.protolayout.*
.من المفترض أن تظل عمليات الاستيراد في
androidx.wear.tiles.EventBuilders
وandroidx.wear.tiles.RequestBuilders
وandroidx.wear.tiles.TileBuilders
وandroidx.wear.tiles.TileService
كما هي.إعادة تسمية بعض الطرق المتوقّفة نهائيًا من فئتَي TileService وTileBuilder:
TileBuilders
: منgetTimeline()
إلىgetTileTimeline()
،setTimeline()
إلىsetTileTimeline()
TileService
: منonResourcesRequest()
إلىonTileResourcesRequest()
RequestBuilders.TileRequest
: منgetDeviceParameters()
إلىgetDeviceConfiguration()
، ومنsetDeviceParameters()
إلىsetDeviceConfiguration()
، ومنgetState()
إلىgetCurrentState()
، ومنsetState()
إلىsetCurrentState()