أنشِئ تطبيقًا كاملاً باستخدام Relay وJetpack Compose

1. قبل البدء

أداة Relay هي مجموعة أدوات تتيح للفِرق تصميم مكوّنات واجهة المستخدم في Figma واستخدامها مباشرةً في مشاريع Jetpack Compose. وبذلك لن تكون هناك حاجة إلى مواصفات التصميم المملة ودورات تأكيد الجودة، ما يساعد الفِرق في تقديم واجهات مستخدم رائعة لنظام التشغيل Android بسرعة.

في هذا الدرس التطبيقي حول الترميز، ستتعلم كيفية دمج حزم واجهة مستخدم Relay في عملية تطوير Compose. وهي تركّز على أساليب الدمج وليس على سير العمل الشامل. للتعرّف على سير العمل العام لتطبيق Relay، يُرجى الاطّلاع على الدليل التوجيهي الأساسي لتطبيق Relay.

المتطلبات الأساسية

  • تجربة أساسية مع Compose. إذا لم يسبق لك إجراء ذلك، أكمِل الدرس التطبيقي حول الترميز أساسيات Jetpack Compose.
  • خبرة في بناء جملة Kotlin.

المعلومات التي ستطّلع عليها

  • كيفية استيراد حزم واجهة المستخدم.
  • كيفية دمج حزم واجهة المستخدم مع التنقل وبنية البيانات.
  • كيفية التفاف حزم واجهة المستخدم بمنطق وحدة التحكم.
  • كيفية تعيين أنماط Figma إلى موضوع Compose.
  • كيفية استبدال حزم واجهة المستخدم بعناصر حالية قابلة للإنشاء في رمز برمجي تم إنشاؤه

ما الذي ستنشئه

  • تصميم تطبيق واقعي بناءً على حزم Relay التي يقدمها المصمم. يُطلق على التطبيق اسم Reflect، وهو تطبيق تتبع يومي يعزز اليقظة والوعي التام والعادات الجيدة. فهو يحتوي على مجموعة من أجهزة التتبع من مختلف الأنواع وواجهة مستخدم لإضافتها وإدارتها. يبدو التطبيق كالصورة التالية:

التطبيق النهائي

المتطلبات

2. الإعداد

الحصول على الرمز

للحصول على التعليمات البرمجية لهذا الدرس التطبيقي حول الترميز، نفِّذ أحد الإجراءات التالية:

$ git clone https://github.com/googlecodelabs/relay-codelabs
  • انتقِل إلى مستودع relay-codelabs على GitHub، واختَر الفرع المطلوب، ثم انقر على الرمز > نزِّل ملف ZIP وفُكَّ حزمة ملف ZIP الذي تم تنزيله.

وفي كلتا الحالتين، يحتوي الفرع main على رمز التفعيل ويحتوي الفرع end على رمز الحلّ.

تثبيت المكوّن الإضافي Relay for Android Studio

إذا لم يكن لديك المكوّن الإضافي Relay for Android Studio، اتَّبِع الخطوات التالية:

  1. في "استوديو Android"، انقر على الإعدادات > Plugins (المكوّنات الإضافية):
  2. في مربّع النص، أدخِل Relay for Android Studio.
  3. في الإضافة التي تظهر في نتائج البحث، انقر على تثبيت.

إعدادات المكوّن الإضافي "استوديو Android"

  1. إذا ظهر لك مربّع الحوار ملاحظة بشأن الخصوصية للمكوّنات الإضافية التابعة لجهات خارجية، انقر على قبول.
  2. انقر على موافق > إعادة التشغيل.
  3. إذا ظهر لك مربع الحوار تأكيد الخروج، انقر على خروج.

ربط "استوديو Android" بتطبيق Figma

يسترد Relay حزم واجهة المستخدم باستخدام واجهة برمجة تطبيقات Figma. لاستخدامه، تحتاج إلى حساب Figma مجاني ورمز دخول شخصي، ولهذا السبب تم إدراجه في قسم ما ستحتاجه.

إذا لم تكن قد ربطت Android Studio بـ Figma بالفعل، فاتبع الخطوات التالية:

  1. في حساب Figma، انقر فوق أيقونة ملفك الشخصي في أعلى الصفحة وحدد Settings (الإعدادات).
  2. في قسم رموز الدخول الشخصية، أدخِل وصفًا للرمز المميّز في مربّع النص، ثم اضغط على Enter (أو return على نظام التشغيل macOS). يتم إنشاء رمز مميّز.
  3. انقر على نسخ هذا الرمز المميّز.

رمز الدخول الذي تم إنشاؤه في Figma

  1. في "استوديو Android"، اختَر الأدوات >. إعدادات الإرسال سيظهر مربع الحوار إعدادات الإرسال.
  2. في مربّع النص رمز الدخول إلى Figma، الصق رمز الدخول، ثم انقر على حسنًا. تم إعداد بيئتك.

3- مراجعة تصميم التطبيق

بالنسبة لتطبيق Reflect، عملنا مع مصمم لمساعدتنا في تحديد لون التطبيق وأسلوب الخط وتخطيطه وسلوكه. لقد أنشأنا هذه التصميمات وفقًا لاصطلاحات Material Design 3 بحيث يعمل التطبيق بسلاسة مع مكونات ومظاهر Material.

مراجعة الشاشة الرئيسية

تعرض الشاشة الرئيسية قائمة بأجهزة التتبُّع التي يحدِّدها المستخدم. ويوفر أيضًا عناصر وظيفية لتغيير يوم النشاط وإنشاء أجهزة تتبُّع أخرى.

الشاشة الرئيسية

في Figma، قام المصمم بتقسيم هذه الشاشة إلى مكونات متعددة، وتحديد واجهات برمجة التطبيقات الخاصة بها، وحزمها مع المكوّن الإضافي ترحيل لـ Figma. بعد تجميع هذه المكوّنات، يمكنك استيرادها إلى مشروع "استوديو Android".

مكوِّن الشاشة الرئيسية

مراجعة شاشة الإضافة/التعديل

وتتيح شاشة الإضافة أو التعديل للمستخدمين إضافة أدوات تتبُّع أو تعديلها. يختلف النموذج المعروض قليلاً حسب نوع جهاز التتبُّع.

شاشة إضافة/تعديل

وبالمثل، يتم تقسيم هذه الشاشة إلى عدة مكونات مجمعة.

إضافة/تعديل مكونات الشاشة

مراجعة المظهر

يتم تنفيذ الألوان وأسلوب الخط لهذا التصميم كأنماط Figma استنادًا إلى أسماء الرموز المميزة لـ Material Design 3. ويوفر هذا إمكانية التشغيل التفاعلي أفضل مع مظاهر Compose ومكونات Material.

أنماط Figma

4. استيراد حزم واجهة المستخدم

قبل أن تتمكن من استيراد حزم واجهة المستخدم إلى مشروعك، تحتاج إلى تحميل مصدر التصميم إلى Figma.

للحصول على الرابط إلى مصدر Figma، اتبع الخطوات التالية:

  1. في Figma، انقر على استيراد ملف، ثم حدد ملف ReflectDesign.fig الموجود في مجلد مشروع CompleteAppCodelab.
  2. انقر بزر الماوس الأيمن على الملف، ثم اختَر نسخ الرابط. ستحتاج إليها في القسم التالي.

88afd168463bf7e5.png

استيراد حِزم واجهة المستخدم إلى المشروع

  1. في "استوديو Android"، افتح مشروع ./CompleteAppCodelab.
  2. انقر على ملف > جديد > استيراد حِزم واجهة المستخدم سيظهر مربّع الحوار استيراد حِزم واجهة المستخدم.
  3. في مربع النص عنوان URL لمصدر Figma، الصق عنوان URL الذي نسخته في القسم السابق.

f75d0c3e17b6f75.png

  1. في مربّع النص مظهر التطبيق، أدخِل com.google.relay.example.reflect.ui.theme.ReflectTheme. يضمن ذلك أنّ المعاينات التي تم إنشاؤها تستخدم المظهر المخصّص.
  2. انقر على التالي. ستظهر لك معاينة لحِزم واجهة المستخدم الخاصة بالملف.
  3. انقر على إنشاء. يتم استيراد الحزم إلى مشروعك.
  4. انتقِل إلى علامة التبويب المشروع، ثم انقر على 2158ffa7379d2b2e.pngسهم الموسَّع بجانب المجلد ui-packages.

مجلد ui-packages

  1. انقر على سهم أداة التوسيع 2158ffa7379d2b2e.pngبجانب أحد مجلدات الحِزم، ثم لاحِظ أنّه يحتوي على ملف المصدر JSON وتبعيات مواد العرض.
  2. افتح ملف المصدر JSON. تعرض وحدة "الإرسال" معاينة للحزمة وواجهة برمجة التطبيقات الخاصة بها.

a6105146c4cfb47.png

إنشاء الرموز البرمجية وإنشاؤها

  1. في أعلى "استوديو Android"، انقر على b3bc77f3c78cac1b.png إنشاء مشروع. تتم إضافة الرمز الذي تم إنشاؤه لكل حزمة إلى المجلد "java/com.google.relay.example.reflect". تحتوي العناصر القابلة للإنشاء التي تم إنشاؤها على جميع معلومات التخطيط والتصميم من تصميم Figma.
  2. افتح ملف com/google/relay/example/reflect/range/Range.kt.
  3. لاحظ أنه يتم إنشاء معاينات إنشاء لكل شكل مكون. إذا لزم الأمر، انقر على تقسيم لعرض الرمز وأجزاء المعاينة جنبًا إلى جنب.

c0d21ab0622ad550.png

5- دمج المكوّنات

في هذا القسم، يمكنك إلقاء نظرة فاحصة على الرمز الذي تم إنشاؤه لأداة تتبُّع مفاتيح التحكّم.

تصميم جهاز تتبع مفتاح التحكّم

  1. في "استوديو Android"، افتح ملف com/google/relay/example/reflect/switch/Switch.kt.

Switch.kt (تم إنشاؤه)

/**
 * This composable was generated from the UI Package 'switch'.
 * Generated code; don't edit directly.
 */
@Composable
fun Switch(
    modifier: Modifier = Modifier,
    isChecked: Boolean = false,
    emoji: String = "",
    title: String = ""
) {
    TopLevel(modifier = modifier) {
        if (isChecked) {
            ActiveOverlay(modifier = Modifier.rowWeight(1.0f).columnWeight(1.0f)) {}
        }
        TopLevelSynth(modifier = Modifier.rowWeight(1.0f)) {
            Label(modifier = Modifier.rowWeight(1.0f)) {
                Emoji(emoji = emoji)
                Title(
                    title = title,
                    modifier = Modifier.rowWeight(1.0f)
                )
            }
            Checkmark {
                if (isChecked) {
                    Icon()
                }
            }
        }
    }
}
  1. لاحظ ما يلي:
  • يتم إنشاء كل التخطيط والتصميم من تصميم Figma.
  • تنقسم العناصر الفرعية إلى عناصر منفصلة قابلة للإنشاء.
  • يتم إنشاء المعاينات القابلة للإنشاء لجميع تنوعات التصميم.
  • أنماط الألوان وأسلوب الخط ذات ترميز ثابت. يمكنك حلّ هذه المشكلة لاحقًا.

تركيب جهاز التتبُّع

  1. في "استوديو Android"، افتح ملف java/com/google/relay/example/reflect/ui/components/TrackerControl.kt. يوفّر هذا الملف بيانات ومنطق تفاعل لأدوات تتبُّع العادات.
  2. أنشئ التطبيق وشغِّله في المحاكي. وفي الوقت الحالي، يُخرج هذا المكوِّن البيانات الأولية من نموذج أداة التتبُّع.

5d56f8a7065066b7.png

  1. استورِد حزمة com.google.relay.example.reflect.switch.Switch إلى الملف.
  2. استبدِل Text(text = trackerData.tracker.toString()) بجزء when يركز على حقل trackerData.tracker.type.
  3. في نص مجموعة when، يمكنك استدعاء الدالة Composable Switch() عندما يكون النوع TrackerType.BOOLEAN.

يجب أن تظهر التعليمة البرمجية على النحو التالي:

TrackerControl.kt

// TODO: replace with Relay tracker components
when (trackerData.tracker.type) {
    TrackerType.BOOLEAN ->
        Switch(
          title = trackerData.tracker.name,
          emoji = trackerData.tracker.emoji
        )
    else ->
        Text(trackerData.tracker.toString())
}
  1. إعادة إنشاء المشروع. تعرض الصفحة الرئيسية الآن جهاز تتبُّع "التبديل" بشكل صحيح كما تم تصميمه باستخدام البيانات المباشرة.

4241e78b9f82075b.png

6- إضافة الحالة والتفاعل

حزم واجهة المستخدم عديمة الحالة. ما يتم عرضه هو نتيجة بسيطة للمعلَمات التي تم تمريرها. ولكن التطبيقات الحقيقية تحتاج إلى التفاعل والحالة. يمكن تمرير معالِجات التفاعل إلى عناصر قابلة للإنشاء مثل أي مَعلمات أخرى، ولكن أين تحتفظ بالحالة التي تعالجها هذه المعالجات؟ كيف تتجنّب تمرير المعالج نفسه لكل مثيل؟ كيف يمكنك تجريد تركيبات الحزم في مواد قابلة لإعادة الاستخدام؟ في هذه الحالات، ننصحك بدمج الحِزم التي تم إنشاؤها في دالة Composable مخصّصة.

التفاف حزم واجهة المستخدم في دالة Composable بوحدة تحكُّم

يتيح لك إحاطة حزم واجهة المستخدم في دالة Composable بوحدة تحكّم تخصيص العرض التقديمي أو منطق النشاط التجاري، وإدارة الحالة المحلية إذا لزم الأمر. لا يزال المصممون يتمتعون بحرية تحديث حزمة واجهة المستخدم الأصلية في Figma دون الحاجة إلى تحديث رمز برنامج التضمين.

لإنشاء وحدة تحكّم في جهاز تتبُّع مفتاح التحكّم، اتّبِع الخطوات التالية:

  1. في "استوديو Android"، افتح ملف java/com/google/relay/example/reflect/ui/components/SwitchControl.kt.
  2. في الدالة Composable SwitchControl()، أدخِل المَعلمات التالية:
  • trackerData: كائن TrackerData
  • modifier: عنصر زخرفي
  • onLongClick: معاودة الاتصال للتفاعل لتفعيل الضغط المطوّل على أدوات التتبّع للتعديل والحذف
  1. أدرِج الدالة Switch() ومرِّر مفتاح التعديل combinedClickable للتعامل مع النقر والضغط مع الاستمرار.
  2. مرِّر القيم من الكائن TrackerData إلى الدالة Switch()، بما في ذلك طريقة isToggled().

تبدو دالة SwitchControl() المكتملة على النحو التالي:

SwitchControl.kt

package com.google.relay.example.reflect.ui.components

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.relay.example.reflect.model.Tracker
import com.google.relay.example.reflect.model.TrackerData
import com.google.relay.example.reflect.model.TrackerType
import com.google.relay.example.reflect.switch.Switch

/*
 * A component for controlling switch-type trackers.
 *
 * SwitchControl is responsible for providing interaction and state management to the stateless
 * composable [Switch] generated by Relay. [onLongClick] provides a way for callers to supplement
 * the control's intrinsic interactions with, for example, a context menu.
 */
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun SwitchControl(
    trackerData: TrackerData,
    modifier: Modifier = Modifier,
    onLongClick: (() -> Unit)? = null,
) {
    Switch(
        modifier
            .clip(shape = RoundedCornerShape(size = 32.dp))
            .combinedClickable(onLongClick = onLongClick) {
                trackerData.toggle()
            },
        emoji = trackerData.tracker.emoji,
        title = trackerData.tracker.name,
        isChecked = trackerData.isToggled(),
    )
}

@Preview
@Composable
fun SwitchControllerPreview() {
    val data = TrackerData(
        Tracker(
            emoji = "🍕",
            name = "Ate Pizza",
            type = TrackerType.BOOLEAN
        )
    )
    SwitchControl(data)
}
  1. في الملف TrackerControl.kt، أزِل عملية الاستيراد Switch ثم استبدِل الدالة Switch() بطلب إلى الدالة SwitchControl().
  2. أضِف حالات وثابتي العدّ TrackerType.RANGE وTrackerType.COUNT.

تبدو مجموعة when المكتملة على النحو التالي:

TrackerControl.kt

when (trackerData.tracker.type) {
    TrackerType.BOOLEAN ->
        SwitchControl(
            trackerData = trackerData,
            onLongClick = { expanded = true },
        )
    TrackerType.RANGE ->
        RangeControl(
            trackerData = trackerData,
            onLongClick = { expanded = true },
        )
    TrackerType.COUNT ->
        ValueControl(
            trackerData = trackerData,
            onLongClick = { expanded = true },
        )
}
  1. إعادة إنشاء المشروع. يمكنك الآن عرض أجهزة التتبُّع والتفاعل معها. اكتملت الشاشة الرئيسية.

b23b94f0034243d3.png

7. ربط المكونات الحالية

تتيح خدمة الإرسال للمطوّرين تخصيص الرموز التي تم إنشاؤها من خلال استبدال حِزم واجهة المستخدم بالعناصر الحالية القابلة للإنشاء. هذه طريقة رائعة لإخراج مكونات غير تقليدية أو حتى أنظمة تصميم مخصصة في التعليمات البرمجية.

ربط حقل نصي

الصورة التالية هي تصميم المكوِّن Tracker Settings في مربّع الحوار إضافة/تعديل أداة تتبُّع:

تصميم لمكون إعدادات التبديل

استخدم مصممنا ReflectTextField في التصميم، والذي لدينا بالفعل تطبيق له في رمز برمجي مُنشأ في أعلى الحقول النصية Material Design 3. لا يدعم Figma الحقول النصية بشكل أصلي، لذا فإن الكود الافتراضي الذي تم إنشاؤه بواسطة Relay يبدو فقط مثل التصميم؛ فهذا ليس تحكمًا وظيفيًا.

لاختبار طريقة التنفيذ الحالية لـ TrackerSettings:

  1. وفي "استوديو Android"، أنشِئ التطبيق وشغِّله في المحاكي.
  2. اضغط مع الاستمرار على صف جهاز التتبُّع واختَر تعديل.
  3. انقر على حقل النص "Title" ولا يستجيب للتفاعل.

لاستبدال التنفيذ الفعلي لهذا العنصر، ستحتاج إلى شيئين: حزمة واجهة مستخدم حقل النص وملف الربط. لحسن الحظ، قام المصمم بالفعل بتعبئة مكونات نظام التصميم لدينا في Figma واستخدم مكون حقل نصي في تصميمه لـ Tracker Settings. يتم إنشاء هذه الحزمة المضمّنة تلقائيًا كملحق، ولكن يمكنك استخدام ربط المكوّنات لاستبدالها.

مكون Figma لحقل نصي مع المكون الإضافي Relay متراكب

إنشاء ملف ربط

يوفر المكوّن الإضافي Relay for Android Studio اختصارًا لإنشاء ملفات تعيين المكونات.

لإنشاء ملف ربط، اتّبِع الخطوات التالية:

  1. في "استوديو Android"، انقر بزر الماوس الأيمن على حزمة واجهة المستخدم text_field، ثم اختَر إنشاء ملف تعيين.

إنشاء عنصر قائمة سياق لملف الربط

  1. سيظهر مربع حوار ملف الربط. أدخِل الخيارات التالية:
  • في الحقل الاستهداف القابل للإنشاء، اختَر استخدام العنصر الحالي القابل للإنشاء وأدخِل com.google.relay.example.reflect.ui.components.ReflectTextField.
  • في ملف تم إنشاؤه، ضَع علامة في المربّع إنشاء عملية تنفيذ وأزِل العلامة من المربّع إنشاء معاينة إنشاء.

e776585c3b838b10.png

  1. انقر على إنشاء ملف ربط. سيؤدي هذا إلى إنشاء ملف الربط التالي:

text_field.json

{
  "target": "ReflectTextField",
  "package": "com.google.relay.example.reflect.ui.components",
  "generateImplementation": true,
  "generatePreviews": false,
}

تحدِّد ملفات ربط المكوّنات هدف وحزمة فئة Compose ومجموعة اختيارية من كائنات fieldMapping. تسمح لك عمليات ربط الحقول هذه بتحويل مَعلمات الحزمة إلى مَعلمات Compose المتوقّعة. في هذه الحالة، تكون واجهات برمجة التطبيقات متطابقة، وبالتالي ما عليك سوى تحديد الفئة المستهدَفة.

  1. إعادة إنشاء المشروع.
  2. في الملف trackersettings/ TrackerSettings.kt، ابحث عن الدالة "TitleFieldStyleFilledStateEnabledTextConfigurationsInputText()" القابلة للتضمين التي تم إنشاؤها، ولاحظ أنّها تتضمّن مكوّن ReflectTextField تم إنشاؤه.

TrackerSettings.kt (تم إنشاؤه)

@Composable
fun TitleFieldStyleFilledStateEnabledTextConfigurationsInputText(
    onTitleChanged: (String) -> Unit,
    title: String,
    modifier: Modifier = Modifier
) {
    ReflectTextField(
        onChange = onTitleChanged,
        labelText = "Title",
        leadingIcon = "search",
        trailingIcon = "cancel",
        supportingText = "Supporting text",
        inputText = title,
        state = State.Enabled,
        textConfigurations = TextConfigurations.InputText,
        modifier = modifier.fillMaxWidth(1.0f).requiredHeight(56.0.dp)
    )
}
  1. إعادة إنشاء المشروع. يمكنك الآن التفاعل مع حقول إعدادات جهاز التتبُّع. اكتملت شاشة التعديل.

8. مظاهر الربط بميزة Compose

ينشئ Relay تلقائيًا قيمًا حرفية للألوان وأسلوب الخط. ويضمن ذلك دقة الترجمة، ولكنه يمنع المكوّنات من استخدام نظام "إنشاء صياغة". ويظهر ذلك بوضوح عند عرض تطبيقك في الوضع الداكن:

معاينة الشاشة الرئيسية باستخدام "الوضع الداكن" وتعرض ألوانًا غير صحيحة

عنصر التنقل اليومي غير مرئي تقريبًا والألوان خاطئة. لإصلاح ذلك، يمكنك استخدام ميزة تعيين الأنماط في Relay لربط أنماط Figma لإنشاء الرموز المميزة للمظاهر في التعليمة البرمجية التي تم إنشاؤها. ويؤدي ذلك إلى زيادة الاتساق المرئي بين مكونات Relay و Material Design 3، كما يتيح دعم الوضع الداكن.

1fac916db14929bb.png

إنشاء ملف ربط أنماط

  1. في "استوديو Android"، انتقِل إلى دليل src/main/ui-package-resources وأنشِئ دليلاً جديدًا باسم style-mappings. في هذا الدليل، أنشئ ملف figma_styles.json يحتوي على الرمز التالي:

figma_styles.json

{
  "figma": {
    "colors": {
      "Reflect Light/background": "md.sys.color.background",
      "Reflect Dark/background": "md.sys.color.background",
      "Reflect Light/on-background": "md.sys.color.on-background",
      "Reflect Dark/on-background": "md.sys.color.on-background",
      "Reflect Light/surface": "md.sys.color.surface",
      "Reflect Dark/surface": "md.sys.color.surface",
      "Reflect Light/on-surface": "md.sys.color.on-surface",
      "Reflect Dark/on-surface": "md.sys.color.on-surface",
      "Reflect Light/surface-variant": "md.sys.color.surface-variant",
      "Reflect Dark/surface-variant": "md.sys.color.surface-variant",
      "Reflect Light/on-surface-variant": "md.sys.color.on-surface-variant",
      "Reflect Dark/on-surface-variant": "md.sys.color.on-surface-variant",
      "Reflect Light/primary": "md.sys.color.primary",
      "Reflect Dark/primary": "md.sys.color.primary",
      "Reflect Light/on-primary": "md.sys.color.on-primary",
      "Reflect Dark/on-primary": "md.sys.color.on-primary",
      "Reflect Light/primary-container": "md.sys.color.primary-container",
      "Reflect Dark/primary-container": "md.sys.color.primary-container",
      "Reflect Light/on-primary-container": "md.sys.color.on-primary-container",
      "Reflect Dark/on-primary-container": "md.sys.color.on-primary-container",
      "Reflect Light/secondary-container": "md.sys.color.secondary-container",
      "Reflect Dark/secondary-container": "md.sys.color.secondary-container",
      "Reflect Light/on-secondary-container": "md.sys.color.on-secondary-container",
      "Reflect Dark/on-secondary-container": "md.sys.color.on-secondary-container",
      "Reflect Light/outline": "md.sys.color.outline",
      "Reflect Dark/outline": "md.sys.color.outline",
      "Reflect Light/error": "md.sys.color.error",
      "Reflect Dark/error": "md.sys.color.error"
    },
    "typography": {
      "symbols": {
        "Reflect/headline/large": "md.sys.typescale.headline-large",
        "Reflect/headline/medium": "md.sys.typescale.headline-medium",
        "Reflect/headline/small": "md.sys.typescale.headline-small",
        "Reflect/title/large": "md.sys.typescale.title-large",
        "Reflect/title/medium": "md.sys.typescale.title-medium",
        "Reflect/title/small": "md.sys.typescale.title-small",
        "Reflect/body/large": "md.sys.typescale.body-large",
        "Reflect/body/medium": "md.sys.typescale.body-medium",
        "Reflect/body/small": "md.sys.typescale.body-small",
        "Reflect/label/large": "md.sys.typescale.label-large",
        "Reflect/label/medium": "md.sys.typescale.label-medium",
        "Reflect/label/small": "md.sys.typescale.label-small"
      },
      "subproperties": {
        "fontFamily": "font",
        "fontWeight": "weight",
        "fontSize": "size",
        "letterSpacing": "tracking",
        "lineHeightPx": "line-height"
      }
    }
  },
  "compose": {
    "colors": {
      "md.sys.color.background": "MaterialTheme.colorScheme.background",
      "md.sys.color.error": "MaterialTheme.colorScheme.error",
      "md.sys.color.error-container": "MaterialTheme.colorScheme.errorContainer",
      "md.sys.color.inverse-on-surface": "MaterialTheme.colorScheme.inverseOnSurface",
      "md.sys.color.inverse-surface": "MaterialTheme.colorScheme.inverseSurface",
      "md.sys.color.on-background": "MaterialTheme.colorScheme.onBackground",
      "md.sys.color.on-error": "MaterialTheme.colorScheme.onError",
      "md.sys.color.on-error-container": "MaterialTheme.colorScheme.onErrorContainer",
      "md.sys.color.on-primary": "MaterialTheme.colorScheme.onPrimary",
      "md.sys.color.on-primary-container": "MaterialTheme.colorScheme.onPrimaryContainer",
      "md.sys.color.on-secondary": "MaterialTheme.colorScheme.onSecondary",
      "md.sys.color.on-secondary-container": "MaterialTheme.colorScheme.onSecondaryContainer",
      "md.sys.color.on-surface": "MaterialTheme.colorScheme.onSurface",
      "md.sys.color.on-surface-variant": "MaterialTheme.colorScheme.onSurfaceVariant",
      "md.sys.color.on-tertiary": "MaterialTheme.colorScheme.onTertiary",
      "md.sys.color.on-tertiary-container": "MaterialTheme.colorScheme.onTertiaryContainer",
      "md.sys.color.outline": "MaterialTheme.colorScheme.outline",
      "md.sys.color.primary": "MaterialTheme.colorScheme.primary",
      "md.sys.color.primary-container": "MaterialTheme.colorScheme.primaryContainer",
      "md.sys.color.secondary": "MaterialTheme.colorScheme.secondary",
      "md.sys.color.secondary-container": "MaterialTheme.colorScheme.secondaryContainer",
      "md.sys.color.surface": "MaterialTheme.colorScheme.surface",
      "md.sys.color.surface-variant": "MaterialTheme.colorScheme.surfaceVariant",
      "md.sys.color.tertiary": "MaterialTheme.colorScheme.tertiary",
      "md.sys.color.tertiary-container": "MaterialTheme.colorScheme.tertiaryContainer"
    },
    "typography": {
      "symbols": {
        "md.sys.typescale.display-large": "MaterialTheme.typography.displayLarge",
        "md.sys.typescale.display-medium": "MaterialTheme.typography.displayMedium",
        "md.sys.typescale.display-small": "MaterialTheme.typography.displaySmall",
        "md.sys.typescale.headline-large": "MaterialTheme.typography.headlineLarge",
        "md.sys.typescale.headline-medium": "MaterialTheme.typography.headlineMedium",
        "md.sys.typescale.headline-small": "MaterialTheme.typography.headlineSmall",
        "md.sys.typescale.title-large": "MaterialTheme.typography.titleLarge",
        "md.sys.typescale.title-medium": "MaterialTheme.typography.titleMedium",
        "md.sys.typescale.title-small": "MaterialTheme.typography.titleSmall",
        "md.sys.typescale.body-large": "MaterialTheme.typography.bodyLarge",
        "md.sys.typescale.body-medium": "MaterialTheme.typography.bodyMedium",
        "md.sys.typescale.body-small": "MaterialTheme.typography.bodySmall",
        "md.sys.typescale.label-large": "MaterialTheme.typography.labelLarge",
        "md.sys.typescale.label-medium": "MaterialTheme.typography.labelMedium",
        "md.sys.typescale.label-small": "MaterialTheme.typography.labelSmall"
      },
      "subproperties": {
        "font": "fontFamily",
        "weight": "fontWeight",
        "size": "fontSize",
        "tracking": "letterSpacing",
        "line-height": "lineHeight"
      }
    },
    "options": {
      "packages": {
        "MaterialTheme": "androidx.compose.material3"
      }
    }
  }
}

يتم تنظيم ملفات ربط المظاهر باستخدام عنصرَين من المستوى الأعلى: figma وcompose. داخل هذه الكائنات، يتم ربط تعريفات الألوان والنوع بين كلتا البيئتين من خلال رموز مميزة وسيطة. يسمح هذا للعديد من أنماط Figma بالتعيين إلى إدخال مظهر Compose مفرد، وهو أمر مفيد عندما تدعم المظاهر الفاتحة والداكنة.

  1. راجع ملف التعيين، خاصة كيفية إعادة تعيين خصائص أسلوب الخط من Figma إلى ما يتوقعه Compose.

إعادة استيراد حِزم واجهة المستخدم

بعد إنشاء ملف تعيين، تحتاج إلى إعادة استيراد جميع حزم واجهة المستخدم إلى مشروعك لأن جميع قيم نمط Figma تم تجاهلها عند الاستيراد الأوّلي نظرًا لعدم توفير ملف تعيين.

لإعادة استيراد حزم واجهة المستخدم، اتبع الخطوات التالية:

  1. في "استوديو Android"، انقر على ملف > جديد > استيراد حِزم واجهة المستخدم سيظهر مربّع الحوار استيراد حِزم واجهة المستخدم.
  2. في مربع نص عنوان URL لمصدر Figma، أدخل عنوان URL لملف مصدر Figma.
  3. ضع علامة في مربّع الاختيار ترجمة أنماط Figma إلى إنشاء المظهر.
  4. اختَر استيراد ضبط مخصّص. انقر على رمز المجلد ثم اختَر الملف الذي أنشأته للتو: src/main/ui-package-resources/style-mappings/figma_styles.json.
  5. انقر على التالي. ستظهر لك معاينة لحِزم واجهة المستخدم الخاصة بالملف.
  6. انقر على إنشاء. يتم استيراد الحزم إلى مشروعك.

مربع حوار استيراد حزم واجهة المستخدم

  1. أعِد إنشاء مشروعك ثم افتح ملف switch/Switch.kt لعرض الرمز الذي تم إنشاؤه.

Switch.kt (تم الإنشاء)

@Composable
fun ActiveOverlay(
    modifier: Modifier = Modifier,
    content: @Composable RelayContainerScope.() -> Unit
) {
    RelayContainer(
        backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
        isStructured = false,
        radius = 32.0,
        content = content,
        modifier = modifier.fillMaxWidth(1.0f).fillMaxHeight(1.0f)
    )
}
  1. لاحِظ كيفية ضبط مَعلمة backgroundColor على الحقل MaterialTheme.colorScheme.surfaceVariant في كائن إنشاء المظهر.
  2. يمكنك تنفيذ المشروع وتفعيل "الوضع الداكن" في المحاكي. تم تطبيق المظهر بشكل صحيح وتم إصلاح الأخطاء المرئية.

6cf2aa19fabee292.png

9. تهانينا

تهانينا! لقد تعلمت كيفية دمج Relay في تطبيقات Compose.

مزيد من المعلومات