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