تتيح لك "معاينات Compose" في استوديو Android فحص عناصر Wear OS القابلة للإنشاء والتحقّق منها على مختلف أحجام شاشات الساعات والإطارات الدائرية ومقاييس الخطوط مباشرةً في بيئة التطوير المتكاملة بدون نشر تطبيقك على ساعة فعلية أو محاكي.
بما أنّ أجهزة Wear OS تتضمّن شاشات دائرية يتم فيها قص المحتوى في الزوايا، وتتضمّن أيضًا تراكبات نظام، مثل TimeText وScrollIndicator، تنحني على طول حافة الشاشة، فإنّ إعداد المعاينات خصيصًا لأجهزة Wear OS أمر ضروري لرصد مشاكل التصميم في وقت مبكر.
إعداد التبعيات الخاصة بالمعاينة
لاستخدام التعليقات التوضيحية لمعاينة Wear OS Compose وتعريفات الأجهزة، أضِف التبعيتَين التاليتَين إلى ملف build.gradle.kts الخاص بالوحدة:
dependencies {
// Provides @WearPreview* multipreview annotations
// (such as @WearPreviewDevices and @WearPreviewFontScales)
implementation("androidx.wear.compose:compose-ui-tooling:1.7.0")
// Provides WearDevices constants
// (such as WearDevices.SMALL_ROUND and WearDevices.LARGE_ROUND)
implementation("androidx.wear:wear-tooling-preview:1.0.0")
// Standard Compose preview support and interactive/animation inspection
implementation("androidx.compose.ui:ui-tooling-preview")
debugImplementation("androidx.compose.ui:ui-tooling")
}
اختيار ما تريد معاينته: الشاشات أو المكوّنات
تعتمد طريقة ضبط المعاينة على ما إذا كنت ستعاين شاشة كاملة أو أحد عناصر واجهة المستخدم المعزولة.
معاينة ملء الشاشة (AppScaffold + ScreenScaffold)
عند معاينة شاشة كاملة، عليك دائمًا تضمين العنصر القابل للإنشاء الخاص بالشاشة في كل من AppScaffold وScreenScaffold باستخدام تعليق توضيحي لمعاينة جهاز Wear. يعرض هذا
شاشة الساعة الدائرية ويضمن ما يلي:
- يتم عرض
TimeTextعلى الحافة المنحنية العلوية لوجه الساعة. - يظهر الرمز
ScrollIndicatorعلى طول الحافة اليمنى. - تم وضع
EdgeButtonبشكل صحيح وتم اقتصاصه عند المنحنى السفلي. - تعكس المساحة المتروكة حول المحتوى واقتصاص الشاشة الدائري بدقة أجهزة الساعات الذكية الحقيقية.
@WearPreviewDevices @Composable fun WorkoutScreenPreview() { MaterialTheme { // AppScaffold provides the top-level TimeText overlay AppScaffold { // WorkoutScreen contains its own ScreenScaffold and content WorkoutScreen( heartRate = 142, elapsedTime = "12:45" ) } } }
دائرة صغيرة (192×192 بكسل)
دائرة كبيرة (227x227dp)
معاينة المكوّنات المعزولة
عند معاينة مكوّنات فردية، مثل Card أو Button أو شريحة الحالة المخصّصة، احذف المَعلمة device واستخدِم @Preview عاديًا بخلفية داكنة. يضمن ذلك ظهور ألوان وتباين Wear Material 3 بشكل دقيق بدون عرض شاشة ساعة دائرية كاملة:
@Preview( showBackground = true, backgroundColor = 0xFF000000 ) @Composable fun HeartRateCardPreview() { MaterialTheme { HeartRateCard(bpm = 142, zone = "Aerobic") } }
معاينة المكوّن المعزول (بدون إطار الجهاز):
التعليقات التوضيحية المضمّنة في ميزة "المعاينة المتعددة"
تقدّم حزمة androidx.wear.compose.ui.tooling.preview تعليقات توضيحية مدمجة
تضبط تلقائيًا الخلفيات الداكنة
(backgroundColor = 0xFF000000 وshowBackground = true) وأبعاد أجهزة الساعات الدائرية:
| تعليق توضيحي | ما يتم عرضه | حالات الاستخدام |
|---|---|---|
@WearPreviewSmallRound |
معاينة واحدة على WearDevices.SMALL_ROUND (192x192dp) |
تكرار سريع على أصغر حجم ممكن لشاشة العرض الدائرية |
@WearPreviewLargeRound |
معاينة واحدة على WearDevices.LARGE_ROUND (227x227dp) |
فحص كثافة التنسيق والمسافات الإضافية على الساعات الأكبر حجمًا |
@WearPreviewDevices |
معاينتان: SMALL_ROUND وLARGE_ROUND |
عملية تحقّق عادية من التوافق مع الأجهزة المتعددة لكل عنصر قابل للإنشاء على الشاشة |
@WearPreviewFontScales |
6 معاينات على SMALL_ROUND في جميع مقاييس خطوط Wear: صغير (0.94f) وعادي (1.0f ومتوسط (1.06f) وكبير (1.12f) وكبير جدًا (1.18f) وأكبر حجم (1.24f). |
التحقّق من التفاف النص واختصاره وتوسيع ارتفاع الزر |
يمكنك تجميع @WearPreviewDevices و@WearPreviewFontScales في دالة معاينة واحدة لإنشاء مصفوفة تجريبية شاملة:
@WearPreviewDevices @WearPreviewFontScales @Composable fun MessageDetailScreenPreview() { MaterialTheme { AppScaffold { MessageDetailScreen( sender = "Alex", body = "Running 5 mins late!" ) } } }
التعليقات التوضيحية المخصّصة للمعاينة ومواصفات الأجهزة
عندما تحتاج إلى تحكّم أدق، مثل اختبار أبعاد أجهزة معيّنة أو سلاسل طويلة مترجمة أو أسوأ الحالات الممكنة، يمكنك ضبط @Preview مباشرةً أو تحديد تعليقات توضيحية مخصّصة خاصة بك للمعاينة المتعدّدة.
الثوابت WearDevices المتاحة ومواصفات الأجهزة المخصّصة
يوفّر العنصر androidx.wear.tooling.preview.devices.WearDevices معرّفات الأجهزة العادية التالية:
-
WearDevices.SMALL_ROUND("id:wearos_small_round"، 192x192 بكسل) WearDevices.LARGE_ROUND("id:wearos_large_round"، 227x227dp)
للمعاينة على شاشات دائرية كبيرة جدًا (مثل الساعات التي يتراوح حجمها بين 44 و45 ملم أو طُرز Ultra بدقة 240x240dp)، مرِّر السلسلة spec: المخصّصة إلى المَعلمة device:
@Preview( name = "XL Round Watch (240dp)", device = "spec:width=240dp,height=240dp,dpi=320,isRound=true", showBackground = true, backgroundColor = 0xFF000000 ) @Composable fun WorkoutScreenXlPreview() { MaterialTheme { AppScaffold { WorkoutScreen(heartRate = 142, elapsedTime = "12:45") } } }
إنشاء تعليق توضيحي مخصّص يتضمّن معاينات متعدّدة
لفحص سيناريو متطرف، أنشئ تعليقًا توضيحيًا مخصّصًا للمعاينة المتعدّدة يربط أصغر شاشة دائرية بأكبر مقياس للخط ولغة تفصيلية (مثل الألمانية) إلى جانب شاشة دائرية كبيرة عادية:
@Preview( name = "1. Standard Large Round", group = "Layout extremes", device = WearDevices.LARGE_ROUND, backgroundColor = 0xFF000000, showBackground = true ) @Preview( name = "2. Extreme Small Round (Largest Font + German)", group = "Layout extremes", device = WearDevices.SMALL_ROUND, fontScale = 1.24f, locale = "de-rDE", backgroundColor = 0xFF000000, showBackground = true ) annotation class WearPreviewExtremes
1. Standard Large Round
2. دائرة صغيرة جدًا (أكبر خط + الألمانية)
معاينة الأعمدة القابلة للتمرير (TransformingLazyColumn)
يتم تلقائيًا تهيئة TransformingLazyColumn باستخدام العنصر الأول
(index = 0) المثبَّت في أعلى الشاشة. ومع ذلك، في Wear OS، يتغيّر ارتفاع العناصر وانحناء زواياها (SurfaceTransformation) عند اقترابها من الحواف المنحنية العلوية والسفلية للشاشة، ولا يظهر الرمز EdgeButton إلا عند الانتقال إلى أسفل الشاشة.
لمعاينة شكل قائمتك عند التمرير جزئيًا للأسفل أو في أسفل القائمة، اتّبِع الخطوات التالية:
الخطوة 1: رفع TransformingLazyColumnState في العنصر القابل للإنشاء على الشاشة
اسمح للعنصر القابل للإنشاء على الشاشة بقبول المَعلمة TransformingLazyColumnState
مع ضبط rememberTransformingLazyColumnState() كقيمة تلقائية:
@Composable fun InboxScreen( messages: List<Message>, columnState: TransformingLazyColumnState = rememberTransformingLazyColumnState(), ) { val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState, edgeButton = { EdgeButton(onClick = { /* Compose new */ }) { Text("New message") } } ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding, ) { items(messages.size) { index -> Card( onClick = {}, modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding( CardDefaults.minimumVerticalListContentPadding ), transformation = SurfaceTransformation(transformationSpec), ) { Text(messages[index].subject) } } } } }
الخطوة 2: تمرير initialAnchorItemIndex في @Preview
تقبل السمة rememberTransformingLazyColumnState مَعلمتَين اختياريتَين للتمرير الأوّلي:
initialAnchorItemIndex: Int: عند ضبطها على فهرس غير سالب (على سبيل المثال،3)، يتم ضبط القائمة على هذا العنصر في منتصف نافذة عرض الساعة.-
initialAnchorItemScrollOffset: Int: إزاحة وحدات البكسل الاختيارية المطبَّقة بالنسبة إلى عنصر المرساة في المنتصف.
يمكنك إنشاء معاينات جنبًا إلى جنب تعرض حالات أعلى ووسط (تم التمرير) وأسفل (EdgeButton مرئي) للشاشة نفسها تمامًا:
@WearPreviewLargeRound @Composable fun InboxScreenTopPreview() { MaterialTheme { AppScaffold { // Default (-1): Pinned to top of list (index 0) InboxScreen(messages = sampleMessages) } } } @WearPreviewLargeRound @Composable fun InboxScreenScrolledMiddlePreview() { MaterialTheme { AppScaffold { // Centers item index 3 in the viewport, showing top/bottom item morphing InboxScreen( messages = sampleMessages, columnState = rememberTransformingLazyColumnState( initialAnchorItemIndex = 3 ) ) } } } @WearPreviewLargeRound @Composable fun InboxScreenBottomEdgeButtonPreview() { MaterialTheme { AppScaffold { // Anchors on the last item so the EdgeButton is visible at the bottom InboxScreen( messages = sampleMessages, columnState = rememberTransformingLazyColumnState( initialAnchorItemIndex = sampleMessages.lastIndex ) ) } } }
في الأعلى (-1 تلقائي)
الوسط (initialAnchorItemIndex = 3)
أسفل الصفحة (EdgeButton موسّع)
ملاحظة: يمكنك أيضًا النقر على بدء "الوضع التفاعلي" على أي
@Previewفي استوديو Android للتمرير فيTransformingLazyColumnمباشرةً باستخدام الماوس أو لوحة التتبّع وفحصSurfaceTransformationالتغيير التدريجي وEdgeButtonالرسوم المتحركة الخاصة بالظهور وScrollIndicatorالحركة في الوقت الفعلي.
الزر "حراسة" ScrollIndicator أثناء التقاط لقطة شاشة قابلة للتمرير (LocalScrollCaptureInProgress)
عندما تلتقط أدوات "التقاط لقطة شاشة قابلة للتمرير" (لقطات شاشة طويلة) أو أدوات اختبار لقطات الشاشة المتعددة الإطارات TransformingLazyColumn، يضبط Compose قيمة LocalScrollCaptureInProgress.current على true أثناء التقاط ودمج مربّعات متعددة من مساحة العرض عموديًا.
بما أنّ ScreenScaffold لا يخفي scrollIndicator تلقائيًا
أثناء عملية التقاط لقطة شاشة قابلة للتمرير، سيظهر تراكب شريط التمرير العائم بشكل متكرر على
كل جزء من لقطة الشاشة الطويلة المجمّعة، ما لم يتم إخفاؤه بشكل صريح باستخدام
!LocalScrollCaptureInProgress.current:
ScreenScaffold( scrollState = columnState, scrollIndicator = { if (!LocalScrollCaptureInProgress.current) { ScrollIndicator(state = columnState) } } ) { contentPadding -> // TransformingLazyColumn content... // ... }