أساسيات إنشاء التصميمات

تسهِّل Jetpack Compose تصميم واجهة المستخدم لتطبيقك وتصميمها. تحوِّل ميزة "الإنشاء" الحالة إلى عناصر في واجهة المستخدم من خلال:

  1. تركيب العناصر
  2. تنسيق العناصر
  3. رسم العناصر

إنشاء حالة التحويل إلى واجهة المستخدم من خلال التركيبة والتنسيق والرسم

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

أهداف التنسيقات في الإنشاء

يتضمن تنفيذ Jetpack Compose لنظام التنسيق هدفين رئيسيين:

أساسيات الدوال القابلة للإنشاء

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

قد تنشئ دالة قابلة للإنشاء عدة عناصر في واجهة المستخدم. مع ذلك، إذا لم تقدّم إرشادات حول كيفية ترتيب هذه العناصر، قد ترتّب هذه العناصر على النحو الذي لا يعجبك. على سبيل المثال، ينشئ هذا الرمز عنصرَين نصيَين:

@Composable
fun ArtistCard() {
    Text("Alfred Sisley")
    Text("3 minutes ago")
}

بدون إرشادات حول طريقة ترتيبها، تضع "الإنشاء" العناصر النصية فوق بعضها، ما يجعلها غير قابلة للقراءة:

عنصران نصيان مرسومان فوق بعضهما، ما يجعل النص غير مقروء

توفّر ميزة "إنشاء" مجموعة من التنسيقات الجاهزة الاستخدام لمساعدتك في ترتيب عناصر واجهة المستخدم، كما تسهّل عليك تحديد التنسيقات الخاصة بك المتخصصة.

مكوّنات التنسيق العادية

في كثير من الحالات، يمكنك فقط استخدام عناصر التنسيق العادية للإنشاء.

يمكنك استخدام Column لوضع العناصر عموديًا على الشاشة.

@Composable
fun ArtistCardColumn() {
    Column {
        Text("Alfred Sisley")
        Text("3 minutes ago")
    }
}

تم ترتيب عنصرَين نصيَين على شكل عمود حتى يصبح النص قابلاً للقراءة.

وبالمثل، يمكنك استخدام Row لوضع العناصر بشكل أفقي على الشاشة. تتوافق كل من Column وRow في ضبط محاذاة العناصر التي تحتوي عليها.

@Composable
fun ArtistCardRow(artist: Artist) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column {
            Text(artist.name)
            Text(artist.lastSeenOnline)
        }
    }
}

تعرِض تنسيقًا أكثر تعقيدًا، مع رسم صغير بجانب عمود من العناصر النصية.

يمكنك استخدام Box لوضع العناصر فوق أخرى. ويتيح Box أيضًا ضبط محاذاة محدّدة للعناصر التي يحتوي عليها.

@Composable
fun ArtistAvatar(artist: Artist) {
    Box {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Icon(Icons.Filled.Check, contentDescription = "Check mark")
    }
}

تعرض عنصرَين مكدَّسَين على بعضهما.

غالبًا ما تكون هذه الوحدات الأساسية هي كل ما تحتاجه. يمكنك كتابة دالة قابلة للدمج لدمج هذه التنسيقات في تنسيق أكثر تعقيدًا ويتناسب مع تطبيقك.

مقارنة ثلاثة تنسيقات بسيطة يمكن إنشاؤها: عمود وصف ومربّع

لضبط موضع الأطفال ضمن Row، يجب ضبط الوسيطة horizontalArrangement وverticalAlignment. بالنسبة إلى Column، اضبط الوسيطة verticalArrangement وhorizontalAlignment:

@Composable
fun ArtistCardArrangement(artist: Artist) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.End
    ) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column { /*...*/ }
    }
}

تمت محاذاة العناصر إلى اليمين

نموذج التنسيق

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

باختصار، يقيس الوالدان قبل أطفالهما، ولكن يتم قياس حجمهما ووضعهما بعد أطفالهما.

ننصحك باستخدام الدالة SearchResult التالية.

@Composable
fun SearchResult() {
    Row {
        Image(
            // ...
        )
        Column {
            Text(
                // ...
            )
            Text(
                // ...
            )
        }
    }
}

تعرض هذه الدالة العرض التدرّجي التالي لواجهة المستخدم.

SearchResult
  Row
    Image
    Column
      Text
      Text

في المثال SearchResult، يتّبع تنسيق العرض التدرّجي لواجهة المستخدم هذا الترتيب:

  1. يُطلب من العقدة الجذر Row قياسها.
  2. تطلب عقدة الجذر Row القياس الأول للطفل، Image.
  3. Image هي عقدة أوراق شجر (أي أنها لا تحتوي على عناصر ثانوية)، لذا يتم الإبلاغ عن الحجم وعرض تعليمات موضع الإعلان.
  4. تطلب العقدة الجذرية Row القياس من طفلها الثاني، Column،.
  5. تطلب العقدة Column من أول عنصر فرعي واحد (Text) لها قياس.
  6. عقدة Text الأولى هي عقدة أوراق، ولذلك تسجّل حجمًا وتعرض تعليمات تحديد موضعها.
  7. تطلب العقدة Column من طفلها الثاني على Text قياسها.
  8. العقدة Text الأخرى هي عقدة أوراق، ولذلك تُبلغ عن الحجم وتعرض تعليمات الموضع.
  9. الآن بعد أن أجرت العقدة Column قياسًا على عناصرها الثانوية وحجمها ووضعها، يمكنها تحديد حجمها وموضعها.
  10. الآن بعد أن أجرت العقدة الجذر Row قياسًا على عناصرها الثانوية وحجمها ووضعها، يمكنها تحديد حجمها وموضعها.

ترتيب القياس والحجم والموضع في العرض التدرّجي لواجهة مستخدم نتائج البحث

الأداء

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

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

ولأنّ القياس وموضع الإعلان هما مراحل فرعية مختلفة من تنسيق التصميم، يمكن تنفيذ أي تغييرات لا تؤثر إلا في موضع العناصر فقط، وليس القياس.

استخدام معدِّلات في تنسيقاتك

كما هو موضّح في مُعدِّلات الإنشاء، يمكنك استخدام المُعدِّلات لتزيين المقتنيات أو زيادتها. المعدِّلات ضرورية لتخصيص التنسيق. على سبيل المثال، سنعرض هنا سلسلة معدِّلات متعددة لتخصيص ArtistCard:

@Composable
fun ArtistCardModifiers(
    artist: Artist,
    onClick: () -> Unit
) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ }
        Spacer(Modifier.size(padding))
        Card(
            elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        ) { /*...*/ }
    }
}

تصميم أكثر تعقيدًا، يستخدم مُعدِّلات لتغيير طريقة ترتيب الرسومات والمناطق التي تستجيب لإدخال المستخدم

في الرمز الوارد أعلاه، لاحظ دوال تعديل مختلفة يتم استخدامها معًا.

  • يُجري clickable تفاعلاً قابلاً للإنشاء على إدخال المستخدم ويعرض تمويجًا.
  • تضع padding مساحة حول أحد العناصر.
  • يجعل fillMaxWidth التعبئة القابلة للإنشاء الحد الأقصى للعرض الذي تم منحه له من ذلك العنصر الرئيسي.
  • تحدّد السمة size() العرض والارتفاع المفضّلَين للعنصر.

التنسيقات القابلة للتمرير

تعرَّف على المزيد من المعلومات حول التنسيقات القابلة للتمرير في مستندات إنشاء الإيماءات.

للاطّلاع على القوائم والقوائم الكسولة، اطّلِع على مستندات إنشاء القوائم.

التنسيقات المتجاوبة

يجب تصميم التنسيق مع مراعاة اتجاهات الشاشة المختلفة وأحجام أشكال الأجهزة. يقدّم تطبيق الإنشاء غير المرغوب فيه بضع آليات لتسهيل استخدام التنسيقات القابلة للإنشاء لتتناسب مع إعدادات الشاشة المختلفة.

القيود

لمعرفة القيود المفروضة من أحد الوالدَين وتصميم التنسيق وفقًا لذلك، يمكنك استخدام BoxWithConstraints. يمكن العثور على القيود المفروضة على القياس في نطاق دالة lambda للمحتوى. يمكنك استخدام قيود القياس التالية لإنشاء تنسيقات مختلفة لإعدادات الشاشة المختلفة:

@Composable
fun WithConstraintsComposable() {
    BoxWithConstraints {
        Text("My minHeight is $minHeight while my maxWidth is $maxWidth")
    }
}

التنسيقات المستندة إلى الخانات

توفّر ميزة "الإنشاء" مجموعة كبيرة من العناصر القابلة للإنشاء بناءً على التصميم المتعدد الأبعاد مع الاعتماد على androidx.compose.material:material (يتم تضمينها عند إنشاء مشروع إنشاء في "استوديو Android") لتسهيل إنشاء واجهة المستخدم. وتتوفّر عناصر مثل Drawer، FloatingActionButton، وTopAppBar.

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

مخطَّط يوضّح الخانات المتاحة في شريط تطبيق Material Components

عادةً ما تستغرق تركيبات lambda content دالة lambda قابلة للإنشاء ( content: @Composable () -> Unit). تعرِض واجهات برمجة تطبيقات الخانات العديد من مَعلمات content للاستخدامات المحدّدة. على سبيل المثال، يسمح لك TopAppBar بتقديم المحتوى للسمة title و navigationIcon وactions.

على سبيل المثال، Scaffold يتيح لك تنفيذ واجهة مستخدم ببنية تنسيق التصميم المتعدد الأبعاد الأساسية. Scaffoldيوفّر خانات لأكثر مكوّنات المادة الأساسية شيوعًا، مثل TopAppBar BottomAppBar FloatingActionButton وDrawer. باستخدام Scaffold، من السهل التأكّد من أنّ هذه المكوّنات في موضعها الصحيح وأنّها تعمل بشكل صحيح.

نموذج تطبيق JetNews، الذي يستخدم Scaffold لتحديد عدة عناصر

@Composable
fun HomeScreen(/*...*/) {
    ModalNavigationDrawer(drawerContent = { /* ... */ }) {
        Scaffold(
            topBar = { /*...*/ }
        ) { contentPadding ->
            // ...
        }
    }
}