تقدّم هذه الصفحة نظرة عامة عالية المستوى على الطبقات المعمارية التي تشكّل Jetpack Compose، والمبادئ الأساسية التي تستند إليها هذه الطبقات.
لا يمثّل Jetpack Compose مشروعًا موحّدًا، بل يتم إنشاؤه من عددٍ من الوحدات التي يتم تجميعها معًا لتشكيل حزمة كاملة. من خلال فهم الوحدات المختلفة التي تشكّل Jetpack Compose، يمكنك إجراء ما يلي:
- استخدام المستوى المناسب من التجريد لإنشاء تطبيقك أو مكتبتك
- فهم الحالات التي يمكنك فيها "الانتقال للأسفل" إلى مستوى أدنى للحصول على مزيد من التحكّم أو التخصيص
- الحدّ من التبعيات
الطبقات
في ما يلي الطبقات الرئيسية في Jetpack Compose:
الشكل 1: الطبقات الرئيسية في Jetpack Compose
يتم إنشاء كل طبقة على المستويات الأدنى، مع دمج الوظائف لإنشاء مكوّنات من مستوى أعلى. تستند كل طبقة إلى واجهات برمجة التطبيقات المتاحة للجميع في الطبقات السفلية لإثبات حدود الوحدة والسماح لك باستبدال أي طبقة في حال احتجت إلى ذلك. لنطّلِع على هذه الطبقات من الأسفل إلى الأعلى.
- وقت التشغيل
- توفّر هذه الوحدة أساسيات وقت تشغيل Compose، مثل
remember
وmutableStateOf
و التعليق التوضيحي@Composable
وSideEffect
. يمكنك إنشاء تطبيقات مباشرةً على هذه الطبقة إذا كنت بحاجة فقط إلى إمكانات إدارة الشجرة في Compose، وليس واجهة المستخدم. - واجهة المستخدم
- تتكون طبقة واجهة المستخدم من وحدات متعددة (
ui-text
،ui-graphics
،ui-tooling
، وما إلى ذلك). تنفِّذ هذه الوحدات أساسيات مجموعة أدوات واجهة المستخدم، مثلLayoutNode
،Modifier
، ومعالجات الإدخال، والتنسيقات المخصّصة، والرسم. يمكنك الاستفادة من هذه الطبقة إذا كنت بحاجة فقط إلى المفاهيم الأساسية لمجموعة أدوات واجهة المستخدم. - الأساس
- توفّر هذه الوحدة وحدات أساسية لا تعتمد على نظام التصميم لواجهة مستخدم ميزة "الإنشاء"،
مثل
Row
وColumn
،LazyColumn
، وإدراك إيماءات معيّنة، وما إلى ذلك. يمكنك الاستفادة من الطبقة الأساسية لإنشاء نظام التصميم الخاص بك. - المادة الأساسية
- توفّر هذه الوحدة تنفيذًا لنظام التصميم المتعدّد الأبعاد ل واجهة مستخدم Compose، ما يوفر نظامًا لاختيار المظاهر ومكوناتًا مصمّمة ومؤشرات موجات الانتشار ورموزًا. يمكنك الاستفادة من هذه الطبقة عند استخدام لغة Material Design في تطبيقك.
مبادئ التصميم
يتمثل المبدأ التوجيهي لواجهة Jetpack Compose في توفير وظائف صغيرة تركّز على وظائف معيّنة ويمكن تجميعها (أو تركيبها) معًا، بدلاً من توفير بضعة مكونات موحّدة. يتمتع هذا النهج بعدد من المزايا.
التحكّم
تميل المكوّنات ذات المستوى الأعلى إلى تقديم المزيد من المساعدة لك، ولكنّها تحدّ من مقدار التحكّم المباشر الذي يمكنك تنفيذه. إذا كنت بحاجة إلى مزيد من التحكّم، يمكنك "الانتقال للأسفل" لاستخدام ملف شخصي على مستوى أقل.
على سبيل المثال، إذا كنت تريد إضافة تأثير متحرك إلى لون مكوّن، يمكنك استخدام واجهة برمجة التطبيقات
animateColorAsState
:
val color = animateColorAsState(if (condition) Color.Green else Color.Red)
ومع ذلك، إذا كنت بحاجة إلى أن يبدأ المكوّن باللون الرمادي دائمًا، لا يمكنك
إجراء ذلك باستخدام واجهة برمجة التطبيقات هذه. بدلاً من ذلك، يمكنك الانتقال إلى المستوى الأدنى
Animatable
لواجهة برمجة التطبيقات:
val color = remember { Animatable(Color.Gray) } LaunchedEffect(condition) { color.animateTo(if (condition) Color.Green else Color.Red) }
تستند واجهة برمجة التطبيقات animateColorAsState
ذات المستوى الأعلى إلى واجهة برمجة التطبيقات
Animatable
ذات المستوى الأدنى. إنّ استخدام واجهة برمجة التطبيقات ذات المستوى الأدنى أكثر تعقيدًا، ولكنه يوفّر مزيدًا من
التحكّم. اختَر مستوى التجريد الذي يناسب احتياجاتك على أفضل وجه.
التخصيص
إنّ تجميع المكوّنات ذات المستوى الأعلى من الوحدات الأساسية الأصغر حجمًا يجعل من السهل
تخصيص المكوّنات إذا لزم الأمر. على سبيل المثال، ألقِ نظرة على
تنفيذ
Button
الذي تقدّمه طبقة Material:
@Composable fun Button( // … content: @Composable RowScope.() -> Unit ) { Surface(/* … */) { CompositionLocalProvider(/* … */) { // set LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { Row( // … content = content ) } } } }
يتم تجميع Button
من 4 مكوّنات:
مادة
Surface
توفّر الخلفية والشكل ومعالجة النقرات وما إلى ذلك
CompositionLocalProvider
يؤدي إلى تغيير شفافية المحتوى عند تفعيل الزر أو إيقافهرمز
ProvideTextStyle
يضبط نمط النص التلقائي المُستخدَمRow
يوفّر سياسة التنسيق التلقائية لمحتوى الزر
لقد حذفنا بعض المَعلمات والتعليقات لجعل البنية أكثر وضوحًا، ولكن
يتكون المكوّن بأكمله من 40 سطرًا تقريبًا من الرمز البرمجي فقط لأنّه يجمع ببساطة
هذه المكوّنات الأربعة لتنفيذ الزر. تعتمد المكوّنات، مثل Button
، على رأي معيّن في المَعلمات التي تعرضها، ما يوازن بين تفعيل التخصيصات
الشائعة وعدد كبير من المَعلمات التي يمكن أن تجعل استخدام المكوّن
أكثر صعوبة. على سبيل المثال، توفّر مكوّنات Material Design تخصيصات محدّدة
في نظام Material Design، ما يسهّل اتّباع مبادئ Material Design.
إذا كنت تريد إجراء تخصيص خارج مَعلمات المكوّن،
يمكنك "الانتقال للأسفل" إلى مستوى فرعي وإنشاء نسخة من المكوّن. على سبيل المثال، يحدِّد Material
Design أنّه يجب أن تكون للأزرار خلفية بلون واحد. إذا كنت تحتاج إلى خلفية متدرجة، لا تتيح مَعلمات Button
هذا الخيار. في هذه الحالة، يمكنك استخدام عملية تنفيذ Button
في Material Design كمرجع وإنشاء المكوّن الخاص بك:
@Composable fun GradientButton( // … background: List<Color>, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Row( // … modifier = modifier .clickable(onClick = {}) .background( Brush.horizontalGradient(background) ) ) { CompositionLocalProvider(/* … */) { // set material LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { content() } } } }
يستمرّ التنفيذ أعلاه في استخدام مكوّنات من طبقة Material،
مثل مفاهيم Material المتعلّقة بالمحتوى الحالي في وضع "الإصدار التجريبي"
وأسلوب النص الحالي. ومع ذلك، يتم استبدال المادة Surface
بمواد
Row
وتنسيقها لتحقيق المظهر المطلوب.
إذا كنت لا تريد استخدام مفاهيم Material على الإطلاق، مثلاً في حال إنشاء نظام تصميم مخصّص لك، يمكنك الاكتفاء باستخدام مكوّنات أساسية للطبقة:
@Composable fun BespokeButton( // … backgroundColor: Color, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Row( // … modifier = modifier .clickable(onClick = {}) .background(backgroundColor) ) { // No Material components used content() } }
تحتفظ أداة Jetpack Compose بأبسط الأسماء للمكونات ذات المستوى الأعلى. على سبيل المثال،
androidx.compose.material.Text
تم إنشاؤه استنادًا إلى
androidx.compose.foundation.text.BasicText
.
يتيح لك ذلك تقديم التنفيذ الخاص بك باستخدام الاسم الأسهل للعثور عليه إذا أردت استبدال المستويات الأعلى.
اختيار المستوى المناسب من التجريد
تعني فلسفة Compose في إنشاء مكوّنات متعددة الطبقات وقابلة لإعادة الاستخدام أنّه يجب عدم استخدام الوحدات الأساسية ذات المستوى الأدنى دائمًا. لا توفّر العديد من المكونات ذات المستوى الأعلى المزيد من الوظائف فحسب، بل تطبّق غالبًا أفضل الممارسات مثل إتاحة إمكانية الاستخدام.
على سبيل المثال، إذا أردت إضافة ميزة التفاعل بالإشارة إلى المكوّن المخصّص،
يمكنك إنشاء ذلك من الصفر باستخدام
Modifier.pointerInput
ولكن هناك مكوّنات أخرى ذات مستوى أعلى تم إنشاؤها على هذا المكوّن والتي قد
توفّر نقطة بداية أفضل، على سبيل المثال
Modifier.draggable
،
Modifier.scrollable
أو Modifier.swipeable
.
كقاعدة عامة، ننصحك بالاعتماد على المكوّن الأكثر شمولاً الذي يقدّم الوظائف التي تحتاجها للاستفادة من أفضل الممارسات التي يتضمنها.
مزيد من المعلومات
اطّلِع على نموذج Jetsnack للاطّلاع على مثال على إنشاء نظام تصميم مخصّص.
أفلام مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون لغة JavaScript غير مفعّلة.
- Kotlin لـ Jetpack Compose
- القوائم والشبكات
- الآثار الجانبية في ميزة "الإنشاء"