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

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

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

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

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

أهداف التنسيقات في ميزة "الإنشاء"

يهدف تنفيذ Jetpack Compose لنظام التنسيق إلى تحقيق غرضَين رئيسيَّين:

أساسيات الدوالّ المركّبة

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

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

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

في حال عدم تقديم إرشادات حول كيفية ترتيبها، تُكدِّس ميزة "الإنشاء" عناصر النص فوق بعضها، ما يجعلها غير قابلة للقراءة:

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

يوفّر تطبيق Compose مجموعة من التنسيقات الجاهزة للاستخدام لمساعدتك في ترتيب عناصر واجهة المستخدم، وتسهيل تحديد التنسيقات الخاصة بك الأكثر تخصصًا.

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

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

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

إذا كان التنسيق يحتاج إلى قياسات متعددة لسبب ما، يوفّر تطبيق Compose نظامًا خاصًا، وهو القياسات الأساسية. يمكنك الاطّلاع على مزيد من المعلومات حول هذه الميزة في مقالة القياسات الأساسية في تنسيقات 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() العرض والارتفاع المفضّلَين للعنصر.

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

اطّلِع على مزيد من المعلومات حول التنسيقات القابلة للتقديم أو الإيقاف في مستندات إيماءات الكتابة.

بالنسبة إلى القوائم والقوائم غير المتزامنة، يمكنك الاطّلاع على مستندات إنشاء القوائم.

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

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

القيود

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

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

التنسيقات المستندة إلى الشرائح

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

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

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

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

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

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

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