توفّر Jetpack Compose تنفيذًا للتصميم المتعدد الأبعاد، وهو نظام تصميم شامل لإنشاء واجهات رقمية. تستند مكوّنات التصميم المتعدد الأبعاد (مثل الأزرار والبطاقات ومفاتيح التبديل وما إلى ذلك) إلى تخصيص التصميم المتعدد الأبعاد، وهي طريقة منهجية لتخصيص التصميم المتعدد الأبعاد بما يعكس العلامة التجارية لمنتجك بشكل أفضل. يتضمّن "تصميم Material" سمات اللون وأسلوب الخط والشكل. عند تخصيص هذه السمات، تنعكس التغييرات تلقائيًا في المكوّنات التي تستخدمها لإنشاء تطبيقك.
تنفِّذ Jetpack Compose هذه المفاهيم باستخدام الدالة المركّبة MaterialTheme:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
اضبط المَعلمات التي تمرّرها إلى MaterialTheme لتحديد مظهر تطبيقك.
اللون
يتم تصميم الألوان في Compose باستخدام الفئة Color، وهي فئة تحتوي على بيانات.
val Red = Color(0xffff0000) val Blue = Color(red = 0f, green = 0f, blue = 1f)
يمكنك تنظيم هذه الألوان بالطريقة التي تريدها (كثوابت ذات مستوى أعلى أو ضمن سينغلتون أو محدّدة مضمن)، ولكننا ننصحك بشدة بتحديد الألوان في المظهر واستردادها من هناك. تتيح هذه الطريقة استخدام المظهر الداكن والمظاهر المتداخلة.
توفّر Compose الفئة Colors لنمذجة نظام ألوان Material. توفّر Colors دوال إنشاء لإنشاء مجموعات من الألوان الفاتحة أو الداكنة:
private val Yellow200 = Color(0xffffeb46) private val Blue200 = Color(0xff91a4fc) // ... private val DarkColors = darkColors( primary = Yellow200, secondary = Blue200, // ... ) private val LightColors = lightColors( primary = Yellow500, primaryVariant = Yellow400, secondary = Blue700, // ... )
بعد تحديد Colors، يمكنك تمريرها إلى MaterialTheme:
MaterialTheme( colors = if (darkTheme) DarkColors else LightColors ) { // app content }
استخدام ألوان المظهر
يمكنك استرداد قيمة Colors التي تم توفيرها للدالة المركّبة MaterialTheme باستخدام MaterialTheme.colors.
Text( text = "Hello theming", color = MaterialTheme.colors.primary )
لون السطح والمحتوى
تقبل العديد من المكوّنات زوجًا من اللون ولون المحتوى:
Surface( color = MaterialTheme.colors.surface, contentColor = contentColorFor(color), // ... ) { /* ... */ } TopAppBar( backgroundColor = MaterialTheme.colors.primarySurface, contentColor = contentColorFor(backgroundColor), // ... ) { /* ... */ }
يتيح لك ذلك ليس فقط ضبط لون عنصر قابل للإنشاء، بل أيضًا توفير لون تلقائي للمحتوى والعناصر القابلة للإنشاء التي يتضمّنها. تستخدم العديد من العناصر القابلة للإنشاء لون المحتوى هذا تلقائيًا. على سبيل المثال، يستند لون Text إلى لون محتوى العنصر الأصل، ويستخدم Icon هذا اللون لضبط درجة اللون.
تستردّ الطريقة contentColorFor() لون "على" المناسب لأي ألوان تصميم. على سبيل المثال، إذا ضبطت لون خلفية primary على Surface، سيتم استخدام هذه الدالة لضبط onPrimary كلون المحتوى.
في حال ضبط لون خلفية غير لون التصميم، يجب أيضًا تحديد لون مناسب للمحتوى. استخدِم LocalContentColor لاسترداد لون المحتوى المفضّل
للخلفية الحالية، في موضع معيّن في التدرّج الهرمي.
قناة ألفا للمحتوى
في كثير من الأحيان، تحتاج إلى تغيير مستوى التركيز على المحتوى لتوضيح أهميته وتوفير تسلسل هرمي مرئي. تنصح اقتراحات إمكانية قراءة النص في التصميم المتعدد الأبعاد باستخدام مستويات مختلفة من التعتيم لنقل مستويات مختلفة من الأهمية.
تنفِّذ Jetpack Compose ذلك باستخدام LocalContentAlpha. يمكنك تحديد قيمة ألفا للمحتوى في التسلسل الهرمي من خلال توفير قيمة لهذا CompositionLocal. يمكن أن تستخدم العناصر القابلة للإنشاء المتداخلة هذه القيمة لتطبيق معالجة ألفا على محتواها. على سبيل المثال، تستخدم Text وIcon بشكل تلقائي تركيبة LocalContentColor المعدَّلة لاستخدام LocalContentAlpha. تحدّد المادة بعض قيم ألفا العادية
(high وmedium وdisabled) التي يتم تصميمها باستخدام
العنصر ContentAlpha.
// By default, both Icon & Text use the combination of LocalContentColor & // LocalContentAlpha. De-emphasize content by setting content alpha CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { Text( // ... ) } CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) { Icon( // ... ) Text( // ... ) }
لمزيد من المعلومات حول CompositionLocal، يمكنك الاطّلاع على البيانات ذات النطاق المحلي باستخدام
CompositionLocal.
ContentAlpha.high. يحتوي السطر الثاني على بيانات وصفية أقل أهمية، وبالتالي يستخدم ContentAlpha.medium.المظهر الداكن
في Compose، يمكنك تنفيذ المظهرين الفاتح والداكن من خلال توفير مجموعات مختلفة من
Colors للدالة البرمجية القابلة للإنشاء MaterialTheme:
@Composable fun MyTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { MaterialTheme( colors = if (darkTheme) DarkColors else LightColors, /*...*/ content = content ) }
في هذا المثال، يتم تضمين MaterialTheme في دالة مركّبة خاصة به، تقبل مَعلمة تحدّد ما إذا كان سيتم استخدام مظهر داكن أم لا. في هذه الحالة، تحصل الدالة على القيمة التلقائية لـ darkTheme من خلال طلب البحث عن إعدادات مظهر الجهاز.
يمكنك استخدام رمز برمجي مثل هذا للتحقّق مما إذا كانت Colors الحالية فاتحة أو داكنة:
val isLightTheme = MaterialTheme.colors.isLight Icon( painterResource( id = if (isLightTheme) { R.drawable.ic_sun_24 } else { R.drawable.ic_moon_24 } ), contentDescription = "Theme" )
تراكبات الارتفاع
في Material، تتلقّى مساحات العرض في المظاهر الداكنة ذات الارتفاعات الأعلى تراكبات الارتفاع التي تخفّف من درجة لون الخلفية. كلما زاد ارتفاع السطح (أي اقترب من مصدر ضوء ضمني)، أصبح السطح أكثر سطوعًا.
تطبِّق الدالة المركّبة Surface هذه التراكبات تلقائيًا عند استخدام الألوان الداكنة، وينطبق ذلك أيضًا على أي دالة مركّبة أخرى في التصميم المتعدد الأبعاد تستخدم مساحة عرض:
Surface( elevation = 2.dp, color = MaterialTheme.colors.surface, // color will be adjusted for elevation /*...*/ ) { /*...*/ }
surface كخلفية. بما أنّ البطاقات وشريط التنقّل السفلي يقعان على مستويات ارتفاع مختلفة عن الخلفية، فإنّ ألوانهما تختلف قليلاً، فاللون في البطاقات أفتح من الخلفية، واللون في شريط التنقّل السفلي أفتح من البطاقات.بالنسبة إلى السيناريوهات المخصّصة التي لا تتضمّن Surface، استخدِم
LocalElevationOverlay، وهو CompositionLocal يحتوي على
ElevationOverlay الذي تستخدمه مكوّنات Surface:
// Elevation overlays // Implemented in Surface (and any components that use it) val color = MaterialTheme.colors.surface val elevation = 4.dp val overlaidColor = LocalElevationOverlay.current?.apply( color, elevation )
لإيقاف التراكبات التي تظهر عند الارتفاع، قدِّم null عند النقطة المحدّدة في التسلسل الهرمي القابل للإنشاء:
MyTheme { CompositionLocalProvider(LocalElevationOverlay provides null) { // Content without elevation overlays } }
لمسات لونية محدودة
تنصح Material باستخدام لمسات ألوان محدودة للمظاهر الداكنة، وذلك من خلال تفضيل استخدام اللون surface على اللون primary في معظم الحالات. تتضمّن عناصر Material القابلة للإنشاء، مثل TopAppBar وBottomNavigation، هذا السلوك تلقائيًا.
بالنسبة إلى السيناريوهات المخصّصة، استخدِم سمة الإضافة primarySurface:
Surface( // Switches between primary in light theme and surface in dark theme color = MaterialTheme.colors.primarySurface, /*...*/ ) { /*...*/ }
أسلوب الخط
تحدّد Material نظام أنواع، ما يشجّعك على استخدام عدد صغير من الأنماط التي تحمل أسماء دلالية.
تنفّذ Compose نظام الأنواع باستخدام الفئات Typography وTextStyle والمتعلّقة بالخطوط. يوفّر الدالة الإنشائية Typography قيمًا تلقائية لكل نمط، لذا يمكنك حذف أي نمط لا تريد تخصيصه:
val raleway = FontFamily( Font(R.font.raleway_regular), Font(R.font.raleway_medium, FontWeight.W500), Font(R.font.raleway_semibold, FontWeight.SemiBold) ) val myTypography = Typography( h1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W300, fontSize = 96.sp ), body1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W600, fontSize = 16.sp ) /*...*/ ) MaterialTheme(typography = myTypography, /*...*/) { /*...*/ }
إذا كنت تريد استخدام خط الكتابة نفسه في كل مكان، حدِّد المَعلمة defaultFontFamily واحذف fontFamily أي عناصر TextStyle:
val typography = Typography(defaultFontFamily = raleway) MaterialTheme(typography = typography, /*...*/) { /*...*/ }
استخدام أنماط النص
يتم الوصول إلى عناصر TextStyle باستخدام MaterialTheme.typography. استرجِع عناصر TextStyle على النحو التالي:
Text( text = "Subtitle2 styled", style = MaterialTheme.typography.subtitle2 )
الشكل
يحدّد التصميم المتعدد الأبعاد نظام أشكال يتيح لك تحديد أشكال للمكوّنات الكبيرة والمتوسطة والصغيرة.
تنفِّذ Compose نظام الأشكال باستخدام الفئة Shapes، ما يتيح لك تحديد CornerBasedShape لكل فئة من فئات الحجم:
val shapes = Shapes( small = RoundedCornerShape(percent = 50), medium = RoundedCornerShape(0f), large = CutCornerShape( topStart = 16.dp, topEnd = 0.dp, bottomEnd = 0.dp, bottomStart = 16.dp ) ) MaterialTheme(shapes = shapes, /*...*/) { /*...*/ }
تستخدم العديد من المكوّنات هذه الأشكال تلقائيًا. على سبيل المثال، تكون القيمة التلقائية لكل من Button وTextField وFloatingActionButton هي small، وتكون القيمة التلقائية لـ AlertDialog هي medium، وتكون القيمة التلقائية لـ ModalDrawer هي large. يمكنك الاطّلاع على مرجع مخطط الأشكال للحصول على عملية الربط الكاملة.
استخدام الأشكال
يتم الوصول إلى عناصر Shape باستخدام MaterialTheme.shapes. يمكنك استرداد عناصر Shape باستخدام رمز مشابه لما يلي:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
الأنماط التلقائية
لا يوجد مفهوم مكافئ في Compose للأنماط التلقائية من Android Views. يمكنك توفير وظائف مشابهة من خلال إنشاء دوال overload قابلة للإنشاء خاصة بك تعمل على تضمين مكوّنات Material. على سبيل المثال، لإنشاء نمط زر، يمكنك تضمين الزر في دالة مركّبة خاصة بك، مع ضبط المَعلمات التي تريد تغييرها أو تحتاج إليها مباشرةً، وعرض المَعلمات الأخرى كمَعلمات للدالة المركّبة التي تحتوي على الزر.
@Composable fun MyButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary ), onClick = onClick, modifier = modifier, content = content ) }
نصوص مركّبة على المظهر
يمكنك تحقيق التأثير نفسه الذي توفّره تراكبات السمات من خلال
Views في Android باستخدام Compose عن طريق تضمين عناصر MaterialTheme القابلة للإنشاء. بما أنّ
MaterialTheme يضبط الألوان والطباعة والأشكال تلقائيًا على قيمة المظهر الحالي،
تحتفظ جميع المَعلمات الأخرى بقيمها التلقائية عندما يضبط المظهر إحدى هذه المَعلمات فقط.
بالإضافة إلى ذلك، عند نقل الشاشات المستندة إلى طرق العرض إلى Compose، احرص على الانتباه إلى استخدامات السمة android:theme. من المحتمل أنّك بحاجة إلى MaterialTheme
في هذا الجزء من شجرة واجهة مستخدم Compose.
في هذا المثال، تستخدم شاشة التفاصيل PinkTheme لمعظم الشاشة،
ثم BlueTheme للقسم ذي الصلة. توضّح لقطة الشاشة والرمز التاليان هذا المفهوم:
@Composable fun DetailsScreen(/* ... */) { PinkTheme { // other content RelatedSection() } } @Composable fun RelatedSection(/* ... */) { BlueTheme { // content } }
حالات المكوّنات
يمكن أن تكون مكونات Material التي يمكن التفاعل معها (النقر عليها أو تبديلها أو غير ذلك) في حالات مرئية مختلفة. تشمل الحالات مفعَّل وغير مفعَّل ومضغوط وما إلى ذلك.
تحتوي العناصر القابلة للإنشاء غالبًا على المَعلمة enabled. يؤدي ضبطها على false إلى منع التفاعل، ويغيّر خصائص مثل اللون والارتفاع لنقل حالة المكوّن بصريًا.
enabled = true (على اليمين) وenabled = false (على اليسار)في معظم الحالات، يمكنك الاعتماد على القيم التلقائية لسمات مثل اللون والارتفاع. إذا كنت بحاجة إلى ضبط القيم المستخدَمة في حالات مختلفة، تتوفّر فئات ودوال ملائمة. إليك مثالاً على زر:
Button( onClick = { /* ... */ }, enabled = true, // Custom colors for different states colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary, disabledBackgroundColor = MaterialTheme.colors.onBackground .copy(alpha = 0.2f) .compositeOver(MaterialTheme.colors.background) // Also contentColor and disabledContentColor ), // Custom elevation for different states elevation = ButtonDefaults.elevation( defaultElevation = 8.dp, disabledElevation = 2.dp, // Also pressedElevation ) ) { /* ... */ }
enabled = true (يسار) وenabled = false (يمين)، مع قيم معدَّلة للّون والارتفاعأمواج
تستخدم مكونات Material التموّجات للإشارة إلى أنّه يتم التفاعل معها. إذا كنت تستخدم MaterialTheme في التسلسل الهرمي، سيتم استخدام Ripple كـ Indication تلقائي داخل أدوات التعديل، مثل clickable وindication.
في معظم الحالات، يمكنك الاعتماد على Ripple التلقائي. إذا كنت بحاجة إلى ضبط مظهرها، يمكنك استخدام RippleTheme لتغيير خصائص مثل اللون والشفافية.
يمكنك توسيع RippleTheme والاستفادة من دالتَي الأدوات المساعدة defaultRippleColor وdefaultRippleAlpha. يمكنك بعد ذلك تقديم مظهر التموج المخصّص في التسلسل الهرمي باستخدام LocalRippleTheme:
@Composable fun MyApp() { MaterialTheme { CompositionLocalProvider( LocalRippleTheme provides SecondaryRippleTheme ) { // App content } } } @Immutable private object SecondaryRippleTheme : RippleTheme { @Composable override fun defaultColor() = RippleTheme.defaultRippleColor( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) @Composable override fun rippleAlpha() = RippleTheme.defaultRippleAlpha( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) }
RippleConfiguration.مزيد من المعلومات
لمزيد من المعلومات حول تخصيص التصميم المتعدد الأبعاد في Compose، يُرجى الرجوع إلى المراجع الإضافية التالية.
اختبارات الرموز
الفيديوهات
مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون JavaScript غير مفعّلة
- أنظمة التصميم المخصّصة في Compose
- نقل البيانات من Material 2 إلى Material 3 في Compose
- تسهيل الاستخدام في ميزة "الكتابة نيابةً عني"