Material 3 Expressive هو التطوّر التالي في التصميم المتعدد الأبعاد، ويتضمّن تصميمًا ومكوّنات وميزات تخصيص محدّثة، مثل الألوان الديناميكية.
يركّز هذا الدليل على نقل البيانات من مكتبة Wear Compose Material 2.5 (androidx.wear.compose) Jetpack إلى مكتبة Wear Compose Material 3 (androidx.wear.compose.material3) Jetpack للتطبيقات.
الأساليب
لترحيل رمز تطبيقك من M2.5 إلى M3، اتّبِع الأسلوب نفسه الموضّح في دليل ترحيل Compose Material، وخاصةً:
- يجب عدم استخدام كل من M2.5 وM3 في تطبيق واحد على المدى الطويل.
- يجب التوقّف عن استخدام مكتبات Horologist Composables أو Compose Layout أو Compose Material، واستخدام المكوّنات في M3 بدلاً منها.
- اتّبِع نهجًا تدريجيًا.
الطلبات التابعة
تتضمّن حزمة M3 إصدارًا منفصلاً عن M2.5:
M2.5
implementation("androidx.wear.compose:compose-material:1.4.0")
التصميم 3
implementation("androidx.wear.compose:compose-material3:1.7.0-alpha04")
يمكنك الاطّلاع على أحدث إصدارات M3 في صفحة إصدارات Wear Compose Material 3.
قدّم الإصدار 1.7.0-alpha04 من مكتبة Wear Compose Foundation بعض المكوّنات الجديدة المصمَّمة للعمل مع مكوّنات Material 3.
وبالمثل، يتضمّن الإصدار SwipeDismissableNavHost من مكتبة Wear Compose Navigation رسمًا متحركًا معدَّلاً عند تشغيله على نظام التشغيل Wear OS 6 (مستوى واجهة برمجة التطبيقات 36) أو الإصدارات الأحدث. عند التحديث إلى إصدار Wear Compose Material 3، ننصحك أيضًا بتحديث مكتبتَي Wear Compose Foundation وNavigation:
implementation("androidx.wear.compose:compose-foundation:1.7.0-alpha04")
implementation("androidx.wear.compose:compose-navigation:1.7.0-alpha04")
المظهر
في كلّ من M2.5 وM3، يُطلق على الدالة المركّبة الخاصة بالمظهر الاسم MaterialTheme، ولكن تختلف حِزم الاستيراد والمَعلمات. في الإصدار M3، تم تغيير اسم المَعلمة Colors إلى ColorScheme، وتم تقديم MotionScheme لتنفيذ عمليات الانتقال.
M2.5
import androidx.wear.compose.material.MaterialTheme
MaterialTheme(
colors = AppColors,
typography = AppTypography,
shapes = AppShapes,
content = content
)
التصميم 3
import androidx.wear.compose.material3.MaterialTheme // ... MaterialTheme( colorScheme = ColorScheme(), typography = Typography(), shapes = Shapes(), motionScheme = MotionScheme.standard(), content = { /*content here*/ } )
اللون
يختلف نظام الألوان في M3 بشكل كبير عن M2.5، فقد زاد عدد مَعلمات الألوان، وأصبحت لها أسماء مختلفة، كما أنّها تتوافق بشكل مختلف مع مكوّنات M3. وينطبق ذلك في Compose على فئة Colors في M2.5 وفئة ColorScheme في M3 والدوال ذات الصلة:
M2.5
import androidx.wear.compose.material.Colors
val appColorScheme: Colors = Colors(
// M2.5 Color parameters
)
التصميم 3
import androidx.wear.compose.material3.ColorScheme // ... val appColorScheme: ColorScheme = ColorScheme( // M3 ColorScheme parameters )
يوضّح الجدول التالي الاختلافات الرئيسية بين الإصدارَين 2.5 و3 من مقياس "إمكانية العرض":
| M2.5 | التصميم 3 |
|---|---|
Color |
تمت إعادة تسميته إلى ColorScheme |
| 13 لونًا | 28 لونًا |
| لا ينطبق | ميزة جديدة لتطبيق المظهر بلون تفاعلي |
| لا ينطبق | ألوان ثانوية جديدة للتعبير بشكل أفضل |
تطبيق مظهر بلون تفاعلي
تتضمّن M3 ميزة جديدة هي سمات الألوان الديناميكية. إذا غيّر المستخدمون ألوان خلفية شاشة الساعة، ستتغيّر الألوان في واجهة المستخدم لتتطابق معها.
استخدِم الدالة dynamicColorScheme لتنفيذ نظام ألوان ديناميكي وتوفير defaultColorScheme كخيار احتياطي في حال عدم توفّر نظام الألوان الديناميكي.
@Composable fun myApp() { val dynamicColorScheme = dynamicColorScheme(LocalContext.current) MaterialTheme(colorScheme = dynamicColorScheme ?: myBrandColors) {} } internal val myBrandColors: ColorScheme = ColorScheme( /* Specify colors here */)
أسلوب الخط
يختلف نظام الكتابة في M3 عن M2.5 ويتضمّن الميزات التالية:
- تسعة أنماط نص جديدة
- خطوط مرنة تتيح تخصيص مقاييس الخطوط لأوزان وعرض واستدارة مختلفة
AnimatedText، الذي يستخدم خطوطًا مرنة
M2.5
import androidx.wear.compose.material.Typography
val Typography = Typography(
// M2.5 TextStyle parameters
)
التصميم 3
import androidx.wear.compose.material3.Typography val Typography = Typography( // M3 TextStyle parameters )
الخطوط المرنة
تتيح Flex Fonts للمصمّمين تحديد عرض ووزن الخط لأنواع معيّنة من الأحجام.
أنماط النص
تتوفّر TextStyles التالية في M3، وتستخدمها تلقائيًا العديد من مكوّنات M3.
| أسلوب الخط | TextStyle |
|---|---|
| الشاشة | displayLarge وdisplayMedium وdisplaySmall |
| العنوان | titleLarge وtitleMedium وtitleSmall |
| التصنيف | labelLarge وlabelMedium وlabelSmall |
| Body | bodyLarge وbodyMedium وbodySmall وbodyExtraSmall |
| عدد | numeralExtraLarge, numeralLarge, numeralMedium, numeralSmall, numeralExtraSmall |
| قوس | arcLarge, arcMedium, arcSmall |
الشكل
يختلف نظام الأشكال في M3 عن M2.5، فقد زاد عدد مَعلمات الأشكال، وتمت تسميتها بشكل مختلف، كما أنّها ترتبط بشكل مختلف بمكوّنات M3. تتوفّر أحجام الأشكال التالية:
- صغير جدًا
- صغير
- متوسطة
- كبير
- كبير جدًا
في Compose، ينطبق ذلك على الفئة M2 Shapes والفئة M3
Shapes:
M2.5
import androidx.wear.compose.material.Shapes
val Shapes = Shapes(
// M2.5 Shapes parameters
)
التصميم 3
import androidx.wear.compose.material3.Shapes val Shapes = Shapes( // M3 Shapes parameters )
استخدِم عملية ربط مَعلمات الأشكال من نقل البيانات من Material 2 إلى Material 3 في Compose كنقطة بداية.
تغيير شكل الكائن
تقدّم M3 ميزة "تغيير الشكل": تتغيّر الأشكال الآن استجابةً للتفاعلات.
يتوفّر سلوك "تغيير الشكل" كصيغة لعدد من الأزرار الدائرية، ويمكنك الاطّلاع على قائمة الأزرار التالية التي تتيح ميزة "تغيير الشكل":
| الأزرار | دالة تغيير الشكل |
|---|---|
IconButton |
تعمل السمة IconButtonDefaults.animatedShape على تحريك زر الرمز عند الضغط عليه |
IconToggleButton |
تعمل السمة IconToggleButtonDefaults.animatedShape على تحريك زر التبديل بين الرموز عند الضغط عليه، بينما تعمل السمة IconToggleButtonDefaults.variantAnimatedShapes على تحريك زر التبديل بين الرموز عند الضغط عليه وعند وضع علامة اختيار أو إزالتها. |
TextButton |
تعمل السمة TextButtonDefaults.animatedShape على تحريك زر النص عند الضغط عليه |
TextToggleButton |
تعمل السمة TextToggleButtonDefaults.animatedShapes على تحريك زر التبديل النصي عند الضغط عليه، بينما تعمل السمة TextToggleButtonDefaults.variantAnimatedShapes على تحريك زر التبديل النصي عند الضغط عليه وعند وضع علامة اختيار أو إزالتها. |
المكوّنات والتنسيق
تتوفّر معظم المكوّنات والتنسيقات من M2.5 في M3، ولكن بعض المكوّنات والتنسيقات في M3 لم تكن متوفّرة في M2.5. بالإضافة إلى ذلك، تتضمّن بعض مكوّنات M3 خيارات أكثر من تلك المتوفّرة في M2.5.
مع أنّ بعض المكوّنات تتطلّب مراعاة اعتبارات خاصة، ننصحك باستخدام عمليات الربط التالية بين الدوال كنقطة بداية:
في ما يلي قائمة كاملة بجميع عناصر Material 3:
وأخيرًا، إليك قائمة ببعض المكوّنات ذات الصلة من مكتبة Wear Compose Foundation:
| Wear Compose Foundation 1.7.0-alpha04 | |
|---|---|
| androidx.wear.compose.foundation.hierarchicalFocusGroup | يُستخدَم لإضافة تعليقات توضيحية إلى العناصر القابلة للإنشاء في أحد التطبيقات، وذلك لتتبُّع الجزء النشط من التركيب وتنسيق التركيز. |
| androidx.wear.compose.foundation.pager.HorizontalPager | أداة عرض صفحات قابلة للتمرير أفقيًا، تم إنشاؤها باستخدام مكوّنات Compose Foundation مع تحسينات خاصة بنظام التشغيل Wear لتحسين الأداء والالتزام بإرشادات Wear OS. |
| androidx.wear.compose.foundation.pager.VerticalPager | أداة عرض صفحات قابلة للتمرير عموديًا، تم إنشاؤها استنادًا إلى مكوّنات Compose Foundation مع تحسينات خاصة بنظام التشغيل Wear لتحسين الأداء والالتزام بإرشادات Wear OS. |
| androidx.wear.compose.foundation.lazy.TransformingLazyColumn | يمكن استخدامها بدلاً من ScalingLazyColumn لإضافة تأثيرات تحويل التمرير إلى كل عنصر. |
الأزرار
تختلف الأزرار في M3 عن تلك في M2.5. تم استبدال شريحة M2.5 بـ
الزر. يوفر تنفيذ Button قيمًا تلقائية لكل من Text وmaxLines وtextAlign. يمكن استبدال هذه القيم التلقائية في العنصر Text.
M2.5
import androidx.wear.compose.material.Chip
//M2.5 Buttons
Chip(...)
CompactChip(...)
Button(...)
التصميم 3
//M3 Buttons Button(onClick = { }){} CompactButton(onClick = { }){} IconButton(onClick = { }){} TextButton(onClick = { }){}
يتضمّن الإصدار M3 أيضًا صيغًا جديدة للأزرار. يمكنك الاطّلاع عليها في نظرة عامة على مرجع Compose Material 3 API.
تقدّم الوحدة M3 زرًا جديدًا: EdgeButton. يتوفّر المنتج EdgeButton بأربعة مقاسات مختلفة: صغير جدًا وصغير ومتوسط وكبير. توفّر عملية التنفيذ EdgeButton قيمة تلقائية لـ maxLines استنادًا إلى الحجم، ويمكن تخصيص هذه القيمة.
إذا كنت تستخدم TransformingLazyColumn أو ScalingLazyColumn، مرِّر EdgeButton إلى ScreenScaffold ليتم تحويله وتغيير شكله عند التمرير بدلاً من إضافة EdgeButton كعنصر القائمة الأخير. راجِع الرمز التالي لمعرفة كيفية استخدام EdgeButton مع ScreenScaffold وTransformingLazyColumn.
val state = rememberTransformingLazyColumnState() ScreenScaffold( scrollState = state, contentPadding = rememberResponsiveColumnPadding( first = ColumnItemType.ListHeader ), edgeButton = { EdgeButton( onClick = { } ) { Text(stringResource(R.string.show)) } } ){ contentPadding -> TransformingLazyColumn(state = state, contentPadding = contentPadding,){ // additional code here } }
سقالة
يختلف Scaffold في M3 عن M2.5، ففي M3، تم استبدال Scaffold بـ AppScaffold وScreenScaffold الجديدين القابلين للإنشاء، إذ يحدّد AppScaffold وScreenScaffold بنية الشاشة وينسّقان عمليات الانتقال بين المكوّنين ScrollIndicator وTimeText.
تسمح AppScaffold ببقاء عناصر الشاشة الثابتة، مثل TimeText، مرئية أثناء عمليات الانتقال داخل التطبيق، مثل التمرير سريعًا لإغلاق الشاشة. يوفر هذا العنصر مساحة لعرض المحتوى الرئيسي للتطبيق، والذي سيتم توفيره عادةً من خلال أحد مكونات التنقّل، مثل SwipeDismissableNavHost
يمكنك تعريف AppScaffold واحد لنشاط واستخدام ScreenScaffold لكل شاشة. يضيف AppScaffold مكوّن TimeText تلقائيًا إلى الشاشات، ويمكنك إلغاء هذا المكوّن إذا أردت تخصيصه باستخدام المَعلمة timeText.
M2.5
import androidx.wear.compose.material.Scaffold
Scaffold {...}
التصميم 3
AppScaffold { val navController = rememberSwipeDismissableNavController() SwipeDismissableNavHost( navController = navController, startDestination = "message_list" ) { composable("message_list") { MessageList(onMessageClick = { id -> navController.navigate("message_detail/$id") }) } composable("message_detail/{id}") { MessageDetail(id = it.arguments?.getString("id")!!) } } } } // Implementation of one of the screens in the navigation @Composable fun MessageDetail(id: String) { // .. Screen level content goes here val scrollState = rememberTransformingLazyColumnState() val padding = rememberResponsiveColumnPadding( first = ColumnItemType.BodyText ) ScreenScaffold( scrollState = scrollState, contentPadding = padding ) { scaffoldPaddingValues -> // Screen content goes here // ...
إذا كنت تستخدم HorizontalPager مع HorizontalPagerIndicator، يمكنك الانتقال إلى HorizontalPagerScaffold. يتم وضع HorizontalPagerScaffold ضمن AppScaffold. تحدّد AppScaffold وHorizontalPagerScaffold بنية Pager وتنسّق عمليات الانتقال بين المكوّنين HorizontalPageIndicator وTimeText.
تعرض HorizontalPagerScaffold HorizontalPageIndicator في منتصف أسفل الشاشة تلقائيًا، وتنسّق عرض TimeText وHorizontalPageIndicator وإخفائهما وفقًا لما إذا كان يتم تقسيم Pager إلى صفحات، ويتم تحديد ذلك من خلال PagerState.
يتوفّر أيضًا مكوّن AnimatedPage جديد، وهو يعرض صفحة متحركة ضمن
Pager مع تأثير التوسيع والتعتيم استنادًا إلى موضعها.
AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) val columnState = rememberTransformingLazyColumnState() val contentPadding = rememberResponsiveColumnPadding( first = ColumnItemType.ListHeader, last = ColumnItemType.BodyText, ) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold( scrollState = columnState, contentPadding = contentPadding ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding ) { item { ListHeader( modifier = Modifier.fillMaxWidth() ) { Text(text = "Pager sample") } } item { if (page == 0) { Text(text = "Page #$page. Swipe right") } else{ Text(text = "Page #$page. Swipe left and right") } } } } } } } }
أخيرًا، يقدّم الإصدار 3 من Material Design VerticalPagerScaffold الذي يتّبع النمط نفسه
المستخدَم في HorizontalPagerScaffold:
AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPagerScaffold(pagerState = pagerState) { VerticalPager( state = pagerState ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { ///… } } } } }
عنصر نائب
هناك بعض التغييرات في واجهة برمجة التطبيقات بين الإصدارين M2.5 وM3.
توفّر Placeholder.PlaceholderDefaults الآن معدِّلَين:
Modifier.placeholder، الذي يتم عرضه بدلاً من المحتوى الذي لم يتم تحميله بعد- تأثير التموّج في العناصر النائبة
Modifier.placeholderShimmerالذي يوفّر تأثير التموّج في العناصر النائبة الذي يتم تشغيله في حلقة رسوم متحركة أثناء انتظار تحميل البيانات.
اطّلِع على الجدول التالي لمعرفة التغييرات الإضافية التي تم إجراؤها على مكوّن Placeholder.
| M2.5 | التصميم 3 |
|---|---|
PlaceholderState.startPlaceholderAnimation |
تمت إزالته |
PlaceholderState.placeholderProgression |
تمت إزالته |
PlaceholderState.isShowContent |
تمت إعادة تسميته إلى !PlaceholderState.isVisible |
PlaceholderState.isWipeOff |
تمت إزالته |
PlaceholderDefaults.painterWithPlaceholderOverlayBackgroundBrush |
تمت إزالته |
PlaceholderDefaults.placeholderBackgroundBrush |
تمت إزالته |
PlaceholderDefaults.placeholderChipColors |
تمت إزالته |
SwipeDismissableNavHost
SwipeDismissableNavHost هو جزء من wear.compose.navigation. وعند استخدام هذا المكوّن مع M3، تعدّل السمة MaterialTheme في M3 السمتَين LocalSwipeToDismissBackgroundScrimColor وLocalSwipeToDismissContentScrimColor.
TransformingLazyColumn
TransformingLazyColumn هو جزء من wear.compose.lazy.foundation ويضيف
إمكانية توسيع نطاق الرسوم المتحركة وتغيير شكلها على عناصر القائمة أثناء التمرير،
ما يؤدي إلى تحسين تجربة المستخدم. ننصح بشدة بأن تنقل التطبيقات بياناتها من
ScalingLazyColumn إلى TransformingLazyColumn.
على غرار ScalingLazyColumn، يوفّر rememberTransformingLazyColumnState() لإنشاء TransformingLazyColumnState يتم تذكّره في جميع التركيبات.
لإضافة رسوم متحركة لتغيير الحجم والشكل، أضِف ما يلي إلى كل عنصر من عناصر القائمة:
Modifier.transformedHeight، التي تتيح لك احتساب الارتفاع المحوَّل للعناصر باستخدامTransformationSpec، يمكنك استخدامrememberTransformationSpec()ما لم تكن بحاجة إلى المزيد من التخصيص.-
SurfaceTransformation
للتأكّد من أنّ المسافة المتروكة صحيحة في أعلى القائمة وأسفلها، استخدِم المعدِّل minimumVerticalContentPadding.
val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding ) { item { ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding), transformation = SurfaceTransformation(transformationSpec) ) { Text(text = "Header") } } // ... other items item { Button( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding), transformation = SurfaceTransformation(transformationSpec), onClick = { /* ... */ }, icon = { Icon( imageVector = Icons.Default.Build, contentDescription = "build", ) }, ) { Text( text = "Build", maxLines = 1, overflow = TextOverflow.Ellipsis, ) } } } }
روابط مفيدة
لمزيد من المعلومات حول نقل البيانات من الإصدار 2.5 إلى الإصدار 3 من Material Design في Compose، يُرجى الرجوع إلى المراجع الإضافية التالية.