يصف التنقل الطريقة التي يتنقل بها المستخدمون في تطبيقك. يتفاعل المستخدمون مع عناصر واجهة المستخدم، عادةً عن طريق النقر عليها، ويستجيب التطبيق من خلال عرض محتوى جديد. إذا أراد المستخدم العودة إلى المحتوى السابق، فإنه يستخدم إيماءة الرجوع أو ينقر على زر الرجوع.
حالة التنقّل في النمذجة
من الطرق المناسبة لنمذجة هذا السلوك استخدام حزمة من المحتوى. وعندما ينتقل المستخدم للأمام إلى محتوى جديد، تتم إضافته إلى أعلى الحزمة. وعندما ينتقل المستخدمون للرجوع من هذا المحتوى، تتم إزالته من الحزمة ويتم عرض المحتوى السابق. في ما يتعلق بالتنقّل، يُشار إلى هذه الحزمة عادةً باسم الأنشطة السابقة لأنّها تمثّل المحتوى الذي يمكن للمستخدم الرجوع إليه.
إنشاء أنشطة سابقة
في Navigation 3، لا تتضمّن الأنشطة السابقة محتوًى فعليًا. بدلاً من ذلك، يحتوي على إشارات إلى المحتوى، تُعرف باسم المفاتيح. يمكن أن تكون المفاتيح من أي نوع، ولكنها عادةً ما تكون فئات بيانات بسيطة وقابلة للتسلسل. يوفّر استخدام المراجع بدلاً من المحتوى المزايا التالية:
- من السهل التنقّل من خلال الضغط على المفاتيح في الأنشطة السابقة.
- طالما أنّ المفاتيح قابلة للتسلسل، يمكن حفظ الأنشطة السابقة في وحدة تخزين دائمة، ما يسمح لها بالبقاء على قيد الحياة بعد تغييرات الإعدادات وإيقاف العملية نهائيًا. هذا مهم لأنّ المستخدمين يتوقعون مغادرة تطبيقك والعودة إليه لاحقًا والمتابعة من حيث توقفوا مع عرض المحتوى نفسه. لمزيد من المعلومات، يُرجى الاطّلاع على حفظ الأنشطة السابقة.
من المفاهيم الأساسية في واجهة برمجة التطبيقات Navigation 3 API أنّك تملك الأنشطة السابقة. المكتبة:
- يتوقّع أن تكون الأنشطة السابقة عبارة عن
List<T>مستندة إلى حالة اللقطة، حيثTهو نوع الأنشطة السابقةkeys. يمكنك استخدامAnyأو تقديم مفاتيحك الخاصة ذات النوع الأكثر قوة. عندما ترى المصطلحين "push" أو "pop"، فإنّ التنفيذ الأساسي هو إضافة عناصر أو إزالتها من نهاية القائمة. - تراقب الأنشطة السابقة وتعكس حالتها في واجهة المستخدم باستخدام
NavDisplay.
يوضّح المثال التالي كيفية إنشاء مفاتيح وأنشطة سابقة، وتعديل الأنشطة السابقة استجابةً لأحداث تنقّل المستخدم:
// Define keys that will identify content data object ProductList data class ProductDetail(val id: String) @Composable fun MyApp() { // Create a back stack, specifying the key the app should start with val backStack = remember { mutableStateListOf<Any>(ProductList) } // Supply your back stack to a NavDisplay so it can reflect changes in the UI // ...more on this below... // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state backStack.add(ProductDetail(id = "ABC")) // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state backStack.removeLastOrNull() }
حلّ المفاتيح للوصول إلى المحتوى
يتم تصميم المحتوى في Navigation 3 باستخدام NavEntry، وهي فئة
تحتوي على دالة مركّبة. وهي تمثّل وجهة، أي جزءًا واحدًا من المحتوى يمكن للمستخدم الانتقال إليه والرجوع منه.
يمكن أن يحتوي NavEntry أيضًا على بيانات وصفية، وهي معلومات حول المحتوى. يمكن قراءة هذه البيانات الوصفية من خلال عناصر الحاوية، مثل NavDisplay، لمساعدتها في تحديد كيفية عرض محتوى NavEntry. على سبيل المثال، يمكن استخدام البيانات الوصفية لإلغاء الصور المتحركة التلقائية لـ NavEntry معيّن. NavEntry
metadata هو خريطة لمفاتيح String لقيم Any، ما يوفّر تخزينًا متعدّد الاستخدامات للبيانات.
لتحويل key إلى NavEntry، عليك إنشاء "موفّر إدخال". هذه دالة تقبل key وتعرض NavEntry لهذا key. ويتم تعريفها عادةً كمَعلمة lambda عند إنشاء NavDisplay.
هناك طريقتان لإنشاء Entry Provider، إما من خلال إنشاء دالة lambda مباشرةً أو باستخدام لغة entryProvider DSL.
إنشاء دالة Entry Provider مباشرةً
يمكنك عادةً إنشاء دالة Entry Provider باستخدام عبارة when، مع
فرع لكل مفتاح من مفاتيحك.
entryProvider = { key -> when (key) { is ProductList -> NavEntry(key) { Text("Product List") } is ProductDetail -> NavEntry( key, metadata = mapOf("extraDataKey" to "extraDataValue") ) { Text("Product ${key.id} ") } else -> { NavEntry(Unit) { Text(text = "Invalid Key: $it") } } } }
استخدام لغة entryProvider الخاصة بالنطاق (DSL)
يمكن للغة entryProvider DSL تبسيط دالة lambda من خلال تجنُّب الحاجة إلى اختبار كل نوع من أنواع المفاتيح وإنشاء NavEntry لكل منها.
استخدِم دالة الإنشاء entryProvider لإجراء ذلك. وتتضمّن أيضًا سلوكًا احتياطيًا تلقائيًا (عرض رسالة خطأ) في حال عدم العثور على المفتاح.
entryProvider = entryProvider { entry<ProductList> { Text("Product List") } entry<ProductDetail>( metadata = mapOf("extraDataKey" to "extraDataValue") ) { key -> Text("Product ${key.id} ") } }
لاحظ ما يلي من المقتطف:
- تُستخدَم السمة
entryلتحديدNavEntryبالنوع المحدّد والمحتوى القابل للإنشاء - تقبل الدالة
entryمَعلمةmetadataلضبطNavEntry.metadata
عرض الأنشطة السابقة
تمثّل الأنشطة السابقة حالة التنقّل في تطبيقك. عندما تتغيّر الأنشطة السابقة، يجب أن تعكس واجهة مستخدم التطبيق الحالة الجديدة للأنشطة السابقة. في Navigation 3، يراقب
NavDisplay الأنشطة السابقة ويعدّل واجهة المستخدم وفقًا لذلك. ويمكنك إنشاؤه باستخدام
المَعلمات التالية:
- تمثّل هذه المَعلمة الأنشطة السابقة، ويجب أن تكون من النوع
SnapshotStateList<T>، حيثTهو نوع مفاتيح الأنشطة السابقة. وهوListيمكن تتبّعه، لذا يؤدي إلى إعادة إنشاءNavDisplayعند تغييره. -
entryProviderلتحويل المفاتيح في الأنشطة السابقة إلى عناصرNavEntry - يمكنك اختياريًا تقديم دالة lambda للمَعلمة
onBack. يتم استدعاء هذا عندما يقوم المستخدم بتشغيل حدث خلفي.
يوضّح المثال التالي كيفية إنشاء NavDisplay.
data object Home data class Product(val id: String) @Composable fun NavExample() { val backStack = remember { mutableStateListOf<Any>(Home) } NavDisplay( backStack = backStack, onBack = { backStack.removeLastOrNull() }, entryProvider = { key -> when (key) { is Home -> NavEntry(key) { ContentGreen("Welcome to Nav3") { Button(onClick = { backStack.add(Product("123")) }) { Text("Click to navigate") } } } is Product -> NavEntry(key) { ContentBlue("Product ${key.id} ") } else -> NavEntry(Unit) { Text("Unknown route") } } } ) }
يعرض NavDisplay تلقائيًا أعلى NavEntry في الأنشطة السابقة في
تنسيق لوحة واحدة. يعرض التسجيل التالي هذا التطبيق أثناء تشغيله:
NavDisplay الإعداد التلقائي مع وجهتَينمراحل نشاط الوجهة
يستخدم NavDisplay LifecycleOwner مخصّصة لتحديد حالة مراحل نشاط
NavEntry استنادًا إلى قيود على مستوى المشهد وقيود على مستوى
الإدخال.
لمزيد من المعلومات حول مراحل النشاط في Compose، يُرجى الاطّلاع على مراحل النشاط في Jetpack Compose.
القيود المفروضة على مراحل النشاط على مستوى المشهد
يدير "NavDisplay" مراحل النشاط لـ "Scene" النشطة. يتم تحديد الحدود القصوى على مستوى المشهد على النحو التالي:
بالنسبة إلى المَشاهد غير المتراكبة:
-
RESUMED: يُسمح به فقط عند استقرار انتقال المشهد وعدم عرض أي مشاهد تراكب نشطة فوقه. -
STARTED: يتم تحديد الحد الأقصى عندSTARTEDأثناء انتقال المشهد، مثل التنقّل للأمام أو للخلف، أو عندما يغطّيه تراكب.
بالنسبة إلى المشاهد التي تظهر فوق المحتوى، مثل مربّعات الحوار أو البطاقات السفلية:
-
RESUMED: يُسمح به فقط لمشهد التراكب العلوي النشط حاليًا. -
STARTED: الحد الأقصى هوSTARTEDلأي مشاهد تراكب أساسية يغطيها تراكب أحدث.
حالة مراحل النشاط على مستوى المبتدئين
تدير المكتبة الحد الأقصى لحالة مراحل النشاط لكل NavEntry
بناءً على توفّره في الأنشطة السابقة:
-
RESUMED: إذا كان الإدخال متوفّرًا في الأنشطة السابقة الحالية، يُسمح لمراحل نشاطه بالوصول إلىRESUMED(وفقًا للحدّ الأقصى على مستوى المشهد). CREATED: إذا لم يعُد الإدخال متاحًا في الأنشطة السابقة، مثلما يحدث عند إزالته من الأنشطة السابقة ولكنّه لا يزال معروضًا على الشاشة أثناء إخفائه، تفرض المكتبة قيودًا صارمة على مراحل نشاطه فيCREATED. يضمن هذا الحدّ توقُّف الإدخالات في الخلفية أو الإدخالات التي يتم الخروج منها عن تنفيذ العمل النشط، مثل جمع التدفقات أو تشغيل الكوروتين المرتبط بحالتَيRESUMEDأوSTARTEDأثناء إنهاء انتقالات الخروج.
كيفية الجمع بينهما
على سبيل المثال، يتم تحديد حالة مراحل النشاط النهائية لـ NavEntry على النحو التالي:
| السيناريو | الحدّ الأقصى على مستوى المشهد | قبعة للمبتدئين | الحدّ الأقصى الفعلي |
|---|---|---|---|
| إدخال نشط، شاشة ثابتة (بدون انتقالات أو تراكبات) | RESUMED |
RESUMED |
RESUMED |
| إدخال نشط أثناء الانتقال (الانتقال إلى أو من) | STARTED |
RESUMED |
STARTED |
| إدخال نشط، مغطّى بتراكب (على سبيل المثال، مربّع حوار مفتوح) | STARTED |
RESUMED |
STARTED |
| إدخال منبثق، مع حركة للخروج | STARTED أو RESUMED |
CREATED |
CREATED |
خلاصة ما سبق ذكره
يوضّح المخطّط البياني التالي كيفية تدفّق البيانات بين العناصر المختلفة في Navigation 3:
أحداث التنقّل تبدأ التغييرات. تتم إضافة المفاتيح أو إزالتها من الأنشطة السابقة استجابةً لتفاعلات المستخدم.
يؤدي التغيير في حالة الأنشطة السابقة إلى استرداد المحتوى. تراقب الدالة
NavDisplay(دالة مركّبة تعرض الأنشطة السابقة) الأنشطة السابقة. في الإعدادات التلقائية، يعرض هذا المكوّن الإدخال الأعلى في الأنشطة السابقة في تنسيق لوحة واحدة. عندما يتغيّر المفتاح العلوي في الأنشطة السابقة، يستخدمNavDisplayهذا المفتاح لطلب المحتوى المقابل من موفّر الإدخال.يوفّر مقدّم الإدخال المحتوى. موفّر الإدخال هو دالة تحوّل مفتاحًا إلى
NavEntry. عند تلقّي مفتاح منNavDisplay، يقدّم موفّر الإدخالNavEntryالمرتبط الذي يحتوي على كلّ من المفتاح والمحتوى.يتم عرض المحتوى. يتلقّى
NavDisplayNavEntryويعرض المحتوى.