يوفّر Jetpack Compose تنفيذًا للتصميم المتعدد الأبعاد، وهو نظام تصميم شامل لإنشاء واجهات رقمية. تستند مكوّنات التصميم المتعدد الأبعاد (الأزرار والبطاقات والمفاتيح وما إلى ذلك) إلى تخصيص التصميم المتعدد الأبعاد، وهو طريقة منهجية لتخصيص التصميم المتعدد الأبعاد ليعكس العلامة التجارية لمنتجك بشكل أفضل. يتضمّن "التصميم المتعدد الأبعاد" سمات اللون وأسلوب الخط والشكل. عند تخصيص هذه السمات، تنعكس تغييراتك تلقائيًا في المكونات التي تستخدمها لإنشاء تطبيقك.
تنفّذ 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() اللون المناسب "on" لأي ألوان في المظهر. على سبيل المثال، إذا ضبطت لون الخلفية primary على
Surface، يتم استخدام هذه الدالة لضبط onPrimary كلون للمحتوى.
إذا ضبطت لون خلفية غير متوافق مع المظهر، عليك أيضًا تحديد لون محتوى مناسب. استخدِم LocalContentColor لاسترداد لون المحتوى المفضّل للخلفية الحالية في موضع معيّن في التسلسل الهرمي.
الإصدار الأولي من المحتوى
غالبًا ما ترغب في تغيير مقدار تركيزك على المحتوى لتوصيل الأهمية وتوفير تسلسل هرمي مرئي. تنصح توصيات وضوح النص في التصميم المتعدد الأبعاد باستخدام مستويات مختلفة من التعتيم للتعبير عن مستويات الأهمية المختلفة.
تنفّذ Jetpack Compose ذلك باستخدام LocalContentAlpha. يمكنك تحديد
إصدار ألفا للمحتوى في تسلسل هرمي من خلال تقديم قيمة لهذه
CompositionLocal. يمكن للدوال المركّبة المُدمَجة استخدام هذه القيمة لتطبيق
معالجة ألفا على محتواها. على سبيل المثال، يستخدم Text وIcon تلقائيًا مجموعة LocalContentColor المعدَّلة لاستخدام LocalContentAlpha. يحدّد Material بعض قيم ألفا العادية
(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 هذه التراكبات تلقائيًا عند استخدام
الألوان الداكنة، وكذلك أي دالة برمجية مركّبة أخرى من Material تستخدم سطحًا:
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 Design بتطبيق ألوان تمييز محدودة للمظاهر
الداكنة من خلال تفضيل استخدام اللون surface على اللون primary في
معظم الحالات. تنفّذ الدوال المركّبة في Material Design، مثل 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 تلقائيًا على الحجم الصغير، ويتم ضبط AlertDialog تلقائيًا على الحجم المتوسط، ويتم ضبط ModalDrawer تلقائيًا على الحجم الكبير. يمكنك الاطّلاع على مرجع مخطط الشكل لمعرفة عملية الربط الكاملة.
استخدام الأشكال
يتم الوصول إلى عناصر Shape باستخدام MaterialTheme.shapes. استرداد عناصر
Shape باستخدام رمز مثل هذا:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
الأنماط التلقائية
لا يوجد مفهوم مكافئ في Compose للأنماط التلقائية من Android
Views. يمكنك توفير وظائف مماثلة من خلال إنشاء دوال مركّبة overload خاصة بك تلتف حول مكوّنات التصميم المتعدد الأبعاد. على سبيل المثال، لإنشاء نمط زر، يمكنك تضمين زر في دالة مركّبة خاصة بك، مع ضبط المَعلمات التي تريد أو تحتاج إلى تغييرها مباشرةً وعرض المَعلمات الأخرى كمَعلمات للدالة المركّبة التي تحتوي عليها.
@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 ) }
تراكبات المظاهر
يمكنك تحقيق ما يعادل تراكبات المظاهر من Android
Views في Compose من خلال دمج الدوال المركّبة MaterialTheme. بما أنّ
MaterialTheme يضبط الألوان والخطوط والأشكال تلقائيًا على قيمة
المظهر الحالي، تحتفظ جميع المَعلمات الأخرى بقيمها التلقائية عندما يضبط المظهر
مَعلمة واحدة فقط من هذه المَعلمات.
علاوةً على ذلك، عند نقل الشاشات المستندة إلى View إلى 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
- أدوات تسهيل الاستخدام في Compose