إنشاء تنقُّل تكيُّفي

تحتوي معظم التطبيقات على عدد قليل من وجهات المستوى الأعلى التي يمكن الوصول إليها من خلال واجهة مستخدم التنقل الأساسية للتطبيق. في النوافذ الصغيرة، مثل شاشة الهاتف العادية، تظهر الوجهات عادةً في شريط تنقل أسفل النافذة. في النافذة الموسعة، مثل تطبيق ملء الشاشة على جهاز لوحي، يكون شريط التنقل بجانب التطبيق عادةً خيارًا أفضل نظرًا لأن عناصر التحكم في التنقل يسهل الوصول إليها أثناء الإمساك بالجانبين الأيسر والأيمن من الجهاز.

يسهِّل NavigationSuiteScaffold التبديل بين واجهات المستخدم للتنقُّل من خلال عرض واجهة المستخدم المناسبة للتنقُّل استنادًا إلى WindowSizeClass. ويشمل ذلك التغيير ديناميكيًا في واجهة المستخدم أثناء تغييرات حجم نافذة وقت التشغيل. السلوك الافتراضي هو عرض أي من مكوّنات واجهة المستخدم التالية:

  • شريط التنقل إذا كان العرض أو الارتفاع مضغوطًا أو إذا كان الجهاز في وضع سطح الطاولة
  • سكة حديدية للتنقل لجميع الخدمات الأخرى
الشكل 1. يعرض NavigationSuiteScaffold شريط تنقل في نوافذ صغيرة.
الشكل 2. يعرض تطبيق "NavigationSuiteScaffold" شريط تنقّل في النوافذ الموسّعة.

إضافة التبعيات

NavigationSuiteScaffold هو جزء من مكتبة مجموعة أدوات التنقل التكيّفي Material3. أضِف تبعية للمكتبة في ملف build.gradle في تطبيقك أو الوحدة:

Kotlin


implementation("androidx.compose.material3:material3-adaptive-navigation-suite")

رائع


implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'

إنشاء سقالة

الجزآن الرئيسيان من NavigationSuiteScaffold هما عناصر مجموعة التنقل ومحتوى الوجهة المحددة. يمكنك تحديد عناصر مجموعة التنقل بشكل مباشر في عنصر قابل للإنشاء، ولكن من الشائع وجود هذه العناصر محددة في مكان آخر، على سبيل المثال، في التعداد:

enum class AppDestinations(
    @StringRes val label: Int,
    val icon: ImageVector,
    @StringRes val contentDescription: Int
) {
    HOME(R.string.home, Icons.Default.Home, R.string.home),
    FAVORITES(R.string.favorites, Icons.Default.Favorite, R.string.favorites),
    SHOPPING(R.string.shopping, Icons.Default.ShoppingCart, R.string.shopping),
    PROFILE(R.string.profile, Icons.Default.AccountBox, R.string.profile),
}

لاستخدام NavigationSuiteScaffold، يجب تتبُّع الوجهة الحالية، ويمكنك إجراء ذلك باستخدام rememberSaveable:

var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }

في المثال التالي، تستخدم المعلمة navigationSuiteItems (النوع) NavigationSuiteScope وظيفة item الخاصة بها لتحديد واجهة المستخدم الخاصة بالتنقّل لوجهة فردية. يتم استخدام واجهة مستخدم الوجهة عبر أشرطة التنقل والقضبان والأدراج. لإنشاء عناصر تنقُّل، يمكنك إجراء التكرار باستخدام AppDestinations (المحددة في المقتطف السابق):

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it }
            )
        }
    }
) {
    // TODO: Destination content.
}

ضمن محتوى الوجهة lambda، استخدِم القيمة currentDestination لتحديد واجهة المستخدم التي يجب عرضها. إذا كنت تستخدم مكتبة تنقل في تطبيقك، فاستخدمها هنا لعرض الوجهة المناسبة. عبارة "عندما" يمكن أن تكفي:

NavigationSuiteScaffold(
    navigationSuiteItems = { /*...*/ }
) {
    // Destination content.
    when (currentDestination) {
        AppDestinations.HOME -> HomeDestination()
        AppDestinations.FAVORITES -> FavoritesDestination()
        AppDestinations.SHOPPING -> ShoppingDestination()
        AppDestinations.PROFILE -> ProfileDestination()
    }
}

تغيير الألوان

ينشئ NavigationSuiteScaffold Surface فوق المنطقة التي تشغلها السقالة بالكامل، عادةً النافذة بالكامل. علاوة على ذلك، ترسم السقالة واجهة مستخدم التنقل الخاصة، مثل NavigationBar. يستخدم كل من السطح وواجهة مستخدم التنقل القيم المحددة في مظهر تطبيقك، ولكن يمكنك إلغاء قيم المظهر.

تحدّد المعلَمة containerColor لون السطح. اللون الافتراضي هو لون الخلفية لنظام الألوان لديك. وتحدّد المَعلمة contentColor لون المحتوى على هذا المحتوى. اللون التلقائي هو لون "on" لما يتم تحديده لـ containerColor. على سبيل المثال، إذا كان containerColor يستخدم اللون background، سيستخدم contentColor اللون onBackground. راجع تصنيف Material Design 3 في Compose لمزيد من التفاصيل حول آلية عمل نظام الألوان. عند تجاوز هذه القيم، استخدِم القيم المحددة في المظهر حتى يدعم تطبيقك أوضاع العرض الداكنة والفاتحة:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    containerColor = MaterialTheme.colorScheme.primary,
    contentColor = MaterialTheme.colorScheme.onPrimary,
) {
    // Content...
}

يتم رسم واجهة مستخدم التنقّل أمام سطح "NavigationSuiteScaffold". يتم توفير القيم التلقائية لألوان واجهة المستخدم من خلال NavigationSuiteDefaults.colors()، ولكن يمكنك إلغاء هذه القيم أيضًا. على سبيل المثال، إذا أردت أن تكون خلفية شريط التنقل شفافة ولكن القيم الأخرى هي الإعدادات التلقائية، عليك إلغاء navigationBarContainerColor:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    navigationSuiteColors = NavigationSuiteDefaults.colors(
        navigationBarContainerColor = Color.Transparent,
    )
) {
    // Content...
}

في النهاية، يمكنك تخصيص كل عنصر في واجهة مستخدم التنقّل. عند استدعاء الدالة item، يمكنك ضبط مثيل NavigationSuiteItemColors. تحدد الفئة ألوان العناصر الموجودة في شريط التنقل وسكة التنقل ودرج التنقل. هذا يعني أنه يمكنك الحصول على ألوان متطابقة عبر كل نوع من أنواع واجهة المستخدم للتنقل، أو يمكنك تغيير الألوان بناءً على احتياجاتك. حدّد الألوان على مستوى NavigationSuiteScaffold لاستخدام مثيل الكائن نفسه لجميع العناصر واطلب الدالة NavigationSuiteDefaults.itemColors() لإلغاء العناصر التي تريد تغييرها فقط:

val myNavigationSuiteItemColors = NavigationSuiteDefaults.itemColors(
    navigationBarItemColors = NavigationBarItemDefaults.colors(
        indicatorColor = MaterialTheme.colorScheme.primaryContainer,
        selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer
    ),
)

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it },
                colors = myNavigationSuiteItemColors,
            )
        }
    },
) {
    // Content...
}

تخصيص أنواع التنقّل

يؤدي السلوك التلقائي NavigationSuiteScaffold إلى تغيير واجهة مستخدم التنقّل استنادًا إلى فئات حجم النافذة. ومع ذلك، قد ترغب في إلغاء هذا السلوك. على سبيل المثال، إذا كان تطبيقك يعرض جزءًا كبيرًا واحدًا من المحتوى لخلاصة، يمكن أن يستخدم التطبيق درج التنقُّل الدائم للنوافذ الموسّعة، ولكنه لا يزال سيعود إلى السلوك التلقائي لفئات النوافذ الصغيرة والمتوسطة الحجم:

val adaptiveInfo = currentWindowAdaptiveInfo()
val customNavSuiteType = with(adaptiveInfo) {
    if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) {
        NavigationSuiteType.NavigationDrawer
    } else {
        NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo)
    }
}

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    layoutType = customNavSuiteType,
) {
    // Content...
}

مصادر إضافية

راجع إرشادات Material Design:

اطّلِع على مكوّنات مكتبة androidx.compose.material3 التالية: