يُبقي تخطيط لوحة الدعم تركيز المستخدم على المحتوى الرئيسي للتطبيق أثناء عرض المعلومات الداعمة ذات الصلة. على سبيل المثال، قد تعرض اللوحة الرئيسية تفاصيل عن فيلم، بينما تعرض اللوحة الداعمة أفلامًا مشابهة أو أفلامًا للمخرج نفسه أو أعمالاً يشارك فيها الممثلون أنفسهم.
لمزيد من التفاصيل، يُرجى الاطّلاع على إرشادات اللوحة الداعمة في Material 3.
تنفيذ لوحة داعمة باستخدام Scaffold
NavigableSupportingPaneScaffold هي دالة مركّبة تسهّل
تنفيذ تصميم لوحة مساعِدة في Jetpack Compose. وتتضمّن SupportingPaneScaffold وتضيف ميزة التنقّل المضمّنة ومعالجة إيماءة إظهار شاشة الرجوع.
يتيح هيكل اللوحة الداعمة ما يصل إلى ثلاث لوحات:
- اللوحة الرئيسية: تعرض المحتوى الأساسي.
- اللوحة الداعمة: توفّر سياقًا أو أدوات إضافية ذات صلة باللوحة الرئيسية.
- اللوحة الإضافية (اختيارية): تُستخدَم للمحتوى التكميلي عند الحاجة.
يتكيف الهيكل بناءً على حجم النافذة:
- في النوافذ الكبيرة، تظهر اللوحتان الرئيسية والداعمة جنبًا إلى جنب.
في النوافذ الصغيرة، تظهر لوحة واحدة فقط في كل مرة، ويتم التبديل بينها أثناء تنقّل المستخدمين.
الشكل 1: تنسيق اللوحة الداعمة
إضافة التبعيات
NavigableSupportingPaneScaffold هو جزء من مكتبة التنسيقات التكيُّفية في Material 3.
أضِف الاعتماديات الثلاث التالية ذات الصلة إلى ملف build.gradle لتطبيقك أو وحدتك:
Kotlin
implementation("androidx.compose.material3.adaptive:adaptive")
implementation("androidx.compose.material3.adaptive:adaptive-layout")
implementation("androidx.compose.material3.adaptive:adaptive-navigation")
أنيق
implementation 'androidx.compose.material3.adaptive:adaptive'
implementation 'androidx.compose.material3.adaptive:adaptive-layout'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation'
adaptive: وحدات أساسية منخفضة المستوى، مثل
HingeInfoوPostureadaptive-layout: التنسيقات التكيّفية، مثل
ListDetailPaneScaffoldوSupportingPaneScaffoldadaptive-navigation: دوال مركّبة للتنقّل داخل اللوحات وفي ما بينها، بالإضافة إلى تنسيقات تكيّفية تتيح التنقّل تلقائيًا، مثل
NavigableListDetailPaneScaffoldوNavigableSupportingPaneScaffold
تأكَّد من أنّ مشروعك يتضمّن الإصدار 1.1.0-beta1 من compose-material3-adaptive أو إصدارًا أحدث.
الموافقة على إيماءة إظهار شاشة الرجوع التنبؤية
لتفعيل الصور المتحركة لإيماءة إظهار شاشة الرجوع في Android 15 أو الإصدارات الأقدم، عليك الموافقة على دعم إيماءة إظهار شاشة الرجوع. للموافقة، أضِف
android:enableOnBackInvokedCallback="true" إلى علامة <application> أو
علامات <activity> الفردية ضمن ملف AndroidManifest.xml.
عندما يستهدف تطبيقك الإصدار 16 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 36) أو الإصدارات الأحدث، يتم تفعيل ميزة "إيماءة إظهار شاشة الرجوع" تلقائيًا.
إنشاء متصفّح
في النوافذ الصغيرة، يتم عرض لوحة واحدة فقط في كل مرة، لذا يمكنك استخدام
ThreePaneScaffoldNavigator للانتقال من لوحة إلى أخرى. أنشِئ مثيلاً لأداة التنقّل
باستخدام rememberSupportingPaneScaffoldNavigator.
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope()
تمرير المتصفّح إلى Scaffold
يتطلّب Scaffold استخدام ThreePaneScaffoldNavigator، وهي واجهة
تمثّل حالة Scaffold، وThreePaneScaffoldValue وPaneScaffoldDirective.
NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { /*...*/ }, supportingPane = { /*...*/ }, )
اللوحة الرئيسية واللوحة الداعمة هما دالتان مركّبتان تحتويان على المحتوى. استخدِم
AnimatedPane لتطبيق الصور المتحركة التلقائية للّوحة أثناء التنقّل. استخدِم
قيمة Scaffold للتحقّق مما إذا كانت لوحة الدعم مخفية. إذا كانت مخفية،
اعرض زرًا يستدعي
navigateTo(SupportingPaneScaffoldRole.Supporting) لعرض
لوحة الدعم.
بالنسبة إلى الشاشات الكبيرة، استخدِم طريقة ThreePaneScaffoldNavigator.navigateBack() لإغلاق اللوحة المساعدة، مع تمرير الثابت BackNavigationBehavior.PopUntilScaffoldValueChange. يؤدي استدعاء هذه الطريقة إلى فرض إعادة تركيب لـ NavigableSupportingPaneScaffold.
أثناء إعادة التركيب، تحقَّق من السمة
ThreePaneScaffoldNavigator.currentDestination لتحديد
ما إذا كان سيتم عرض لوحة الدعم.
في ما يلي تنفيذ كامل لنموذج Scaffold:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() val backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { AnimatedPane( modifier = Modifier .safeContentPadding() .background(Color.Red) ) { if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) { Button( modifier = Modifier .wrapContentSize(), onClick = { scope.launch { scaffoldNavigator.navigateTo(SupportingPaneScaffoldRole.Supporting) } } ) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } }, supportingPane = { AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = Modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } } )
استخراج الدوال المركّبة للوحة
استخرِج الأجزاء الفردية من SupportingPaneScaffold إلى دوال مركّبة خاصة بها
لجعلها قابلة لإعادة الاستخدام والاختبار. استخدِم ThreePaneScaffoldScope
للوصول إلى AnimatedPane إذا أردت استخدام الصور المتحركة التلقائية:
@OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.MainPane( shouldShowSupportingPaneButton: Boolean, onNavigateToSupportingPane: () -> Unit, modifier: Modifier = Modifier, ) { AnimatedPane( modifier = modifier.safeContentPadding() ) { // Main pane content if (shouldShowSupportingPaneButton) { Button(onClick = onNavigateToSupportingPane) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } } @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.SupportingPane( scaffoldNavigator: ThreePaneScaffoldNavigator<Any>, modifier: Modifier = Modifier, backNavigationBehavior: BackNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange, ) { val scope = rememberCoroutineScope() AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } }
يؤدي استخراج الأجزاء إلى دوال مركّبة إلى تبسيط استخدام
SupportingPaneScaffold (قارِن ما يلي بالتنفيذ الكامل
للسقالة في القسم السابق):
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) }, )
إذا كنت بحاجة إلى مزيد من التحكّم في جوانب معيّنة من الهيكل، ننصحك باستخدام
SupportingPaneScaffold بدلاً من NavigableSupportingPaneScaffold. تقبل هذه السمة PaneScaffoldDirective وThreePaneScaffoldValue أو ThreePaneScaffoldState بشكل منفصل. تتيح لك هذه المرونة تنفيذ منطق مخصّص للمسافات بين الأجزاء وتحديد عدد الأجزاء التي يجب عرضها في الوقت نفسه. يمكنك أيضًا تفعيل ميزة "إيماءة إظهار شاشة الرجوع" من خلال إضافة
ThreePaneScaffoldPredictiveBackHandler.
إضافة ThreePaneScaffoldPredictiveBackHandler
أضِف معالج إيماءة إظهار شاشة الرجوع الذي يتلقّى مثيل ScaffoldNavigator وحدِّد backBehavior. يحدّد هذا الخيار كيفية إزالة الوجهات من
حزمة الرجوع أثناء التنقّل للخلف. بعد ذلك، مرِّر scaffoldDirective وscaffoldState إلى SupportingPaneScaffold. استخدِم التحميل الزائد الذي يقبل
ThreePaneScaffoldState، مع تمرير scaffoldNavigator.scaffoldState.
تحديد اللوحات الرئيسية والداعمة ضمن SupportingPaneScaffold استخدِم
AnimatedPane للرسوم المتحركة التلقائية في اللوحة.
بعد تنفيذ هذه الخطوات، من المفترض أن يظهر الرمز على النحو التالي:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() ThreePaneScaffoldPredictiveBackHandler( navigator = scaffoldNavigator, backBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange ) SupportingPaneScaffold( directive = scaffoldNavigator.scaffoldDirective, scaffoldState = scaffoldNavigator.scaffoldState, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) }, )