Navigation Component — ما هو، NavHost و Navigation Graph

المؤلف: IT Sectr نُشر: 2026-02-22 وقت القراءة: 7 دق

Navigation Component هي مكتبة Android Jetpack لتنفيذ التنقل بين شاشات التطبيق. يقوم المكون بمركزية إدارة مكدس الأجزاء والروابط العميقة وتمرير الوسائط. وهي جزء من Jetpack منذ 2018 وتوصي بها Google لجميع المشاريع الجديدة. اقرأ المزيد في الدليل الرسمي من Google.

الرئيسية

  • Navigation Component — مكتبة Jetpack للتنقل المركزي بين شاشات Android
  • NavGraph — مورد XML يصف جميع الشاشات والاتصالات بينها
  • NavHostFragment — حاوية في تخطيط Activity تعرض شاشة التنقل الحالية
  • NavController — كائن التحكم في التنقل: navigate، popBackStack، navigateUp
  • Safe Args — إضافة Gradle لتمرير الوسائط بأمان أنواعها بين الشاشات

ما هو Navigation Component؟

Navigation Component هي مكتبة Android Jetpack (androidx.navigation) توفر API موحد للتنقل. تتضمن ثلاثة عناصر رئيسية: Navigation Graph (الرسم البياني للتنقل)، NavHostFragment (حاوية الشاشات) و NavController (التحكم في الانتقالات). يدير المكون مكدس العودة تلقائياً ويدعم الروابط العميقة.

قبل Navigation Component، كان المطورون يديرون الأجزاء يدوياً عبر FragmentManager. أدى هذا إلى كود مجزأ: كل شاشة لها قواعد التنقل الخاصة بها، وحالات مكدس العودة مختلفة، والروابط العميقة تتطلب تنفيذاً منفصلاً. قام Navigation Component بتوحيد هذه السيناريوهات. وفقاً لـ Google (2026)، المكتبة مثبتة في 90% من مشاريع Android الجديدة.

Navigation Component يتكامل مع مكتبات Jetpack الأخرى: LiveData، ViewModel، Material Design. يدعم كلاً من أجزاء XML و Jetpack Compose عبر إضافة navigation-compose. الإصدار المستقر — 2.8.x (2025)، الحد الأدنى لإصدار Android — API 14.

NavGraph هو مورد XML (res/navigation/nav_graph.xml) يحدد جميع شاشات التطبيق والاتصالات بينها. كل شاشة هي وجهة، يمكن أن تكون Fragment أو Activity أو Composable. الاتصالات بين الوجهات هي إجراءات تحدد اتجاه الانتقال.

xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@+id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name=".HomeFragment"
        android:label="الرئيسية"
        tools:layout="@layout/fragment_home">
        <action
            android:id="@+id/action_home_to_detail"
            app:destination="@+id/detailFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
    </fragment>

    <fragment
        android:id="@+id/detailFragment"
        android:name=".DetailFragment"
        android:label="التفاصيل"
        tools:layout="@layout/fragment_detail">
        <argument android:name="itemId"
            app:argType="integer"
            android:defaultValue="0" />
    </fragment>
</navigation>

السمة startDestination تحدد أول شاشة تظهر عند التشغيل. الإجراء يحدد الوجهة المستهدفة والرسوم المتحركة الاختيارية. الوسائط تصف المعاملات المرسلة إلى الشاشة — النوع والقيمة الافتراضية.

NavHostFragment عبارة عن حاوية توضع في تخطيط Activity وتعرض شاشة التنقل الحالية. يقوم NavHostFragment تلقائياً بتبديل الأجزاء عند استدعاء NavController.navigate(). NavController هو الكائن الذي يدير التنقل: الانتقالات، العودة، والتحقق من المسار الحالي.

kotlin
// Layout Activity: activity_main.xml
// <androidx.fragment.app.FragmentContainerView
//     android:id="@+id/nav_host_fragment"
//     android:name="androidx.navigation.fragment.NavHostFragment"
//     app:navGraph="@navigation/nav_graph"
//     app:defaultNavHost="true" />

class MainActivity : AppCompatActivity() {

    private val navController by lazy {
        (findViewById<NavHostFragment>(R.id.nav_host_fragment))
            .navController
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // NavigationUI تربط NavController مع AppBar
        setupActionBarWithNavController(navController)
    }

    // الانتقال إلى شاشة التفاصيل
    fun openDetail(itemId: Long) {
        val bundle = Bundle().apply {
            putLong("itemId", itemId)
        }
        navController.navigate(R.id.action_home_to_detail, bundle)
    }

    override fun onSupportNavigateUp() = 
        navController.navigateUp() || super.onSupportNavigateUp()
}

app:defaultNavHost="true" سمة مهمة: تعترض زر العودة النظامي وتحول التحكم إلى NavController. NavigationUI هي أداة لربط NavController مع AppBar و BottomNavigationView و NavigationDrawer. setupActionBarWithNavController تفعّل سهم العودة على الشاشات المتداخلة.

Navigation Component يدعم رسوم متحركة مخصصة للانتقالات، محددة في الإجراءات أو برمجياً. تُعرف الرسوم المتحركة بأربع سمات: enterAnim (ظهور شاشة جديدة)، exitAnim (اختفاء الشاشة الحالية)، popEnterAnim (الظهور عند العودة) و popExitAnim (الاختفاء عند العودة).

xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="100%"
        android:toXDelta="0%"
        android:duration="300" />
</set>

// انتقال برمجي مع رسوم متحركة
val navOptions = NavOptions.Builder()
    .setEnterAnim(R.anim.slide_in_right)
    .setExitAnim(R.anim.slide_out_left)
    .setPopEnterAnim(R.anim.slide_in_left)
    .setPopExitAnim(R.anim.slide_out_right)
    .build()

navController.navigate(R.id.detailFragment, args, navOptions)

تعمل الرسوم المتحركة مع Fragment على مستوى FragmentTransaction. بالنسبة لـ Jetpack Compose، تُضبط الرسوم المتحركة عبر NavOptionsCompat باستخدام Compose Animation. Navigation Component لا يفرض قيوداً على نوع الرسوم المتحركة — يدعم translate و scale و alpha ومجموعاتها.

Safe Args: وسائط آمنة الأنواع

Safe Args هي إضافة Gradle لنقل البيانات بأمان بين الشاشات. تقوم الإضافة بتحليل NavGraph وتوليد فئات Directions و Args بأنواع حقول محددة. يتم التحقق من تطابق الأنواع في وقت الترجمة — يتم اكتشاف MissingArgumentException قبل تشغيل التطبيق.

kotlin
// build.gradle (module)
plugins {
    id 'androidx.navigation.safeargs.kotlin'
}

// Safe Args يولد: DetailFragmentArgs, HomeFragmentDirections
// الاستخدام في HomeFragment:
val action = HomeFragmentDirections
    .actionHomeToDetail(itemId = 42L)
findNavController().navigate(action)

// الاستخدام في DetailFragment:
private val args: DetailFragmentArgs by navArgs()
// args.itemId من نوع Long، لا يمكن تمرير null

override fun onViewCreated(...) {
    super.onViewCreated(...)
    loadItem(args.itemId)
}

navArgs() هو مفوض Kotlin لاسترجاع الوسائط في Fragment أو Activity. تدعم الإضافة الأنواع البدائية والسلاسل و Parcelable و Serializable و Enum والمصفوفات. للكائنات المعقدة، قم بتمرير معرف وتحميل من ViewModel أو قاعدة البيانات.

Deep Link هو رابط خارجي يفتح شاشة محددة من التطبيق. يعالج Navigation Component الروابط العميقة عبر السمة app:deepLink في NavGraph. يقوم النظام بإنشاء PendingIntent يستعيد مكدس التنقل إلى الشاشة المستهدفة، أو ينشئ مكدساً جديداً إذا كان التطبيق لا يعمل.

xml

<fragment android:id="@+id/profileFragment"
    android:name=".ProfileFragment">
    <deepLink
        app:uri="https://example.com/profile/{userId}" />
    <argument
        android:name="userId"
        app:argType="string" />
</fragment>

// إنشاء برمجي لـ Deep Link
val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.profileFragment)
    .setArguments(Bundle().apply {
        putString("userId", "user_123")
    })
    .createPendingIntent()

تدعم الروابط العميقة أنماط URI مع مسارات ومعاملات استعلام، intent action ونوع mime. العناصر النائبة ({userId}) تُربط تلقائياً بوسائط الوجهة. يعالج Navigation Component أيضاً الروابط العميقة الضمنية عبر AndroidManifest — يكفي إضافة intent-filter إلى Activity الذي يحتوي على NavHostFragment.

Navigation Compose (androidx.navigation:navigation-compose) هو امتداد لـ Navigation Component لـ Jetpack Compose. تحافظ API على مفهوم NavController و NavHost، لكن الشاشات هي دوال Composable بدلاً من Fragment. يقبل NavHost لامدا composable لكل مسار.

kotlin
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyAppTheme {
                val navController = rememberNavController()
                NavHost(
                    navController = navController,
                    startDestination = "home"
                ) {
                    composable("home") {
                        HomeScreen(
                            onItemClick = { id ->
                                navController.navigate("detail/$id")
                            }
                        )
                    }
                    composable(
                        route = "detail/{itemId}",
                        arguments = listOf(
                            navArgument("itemId") {
                                type = NavType.LongType
                            }
                        )
                    ) { backStackEntry ->
                        val itemId = backStackEntry
                            .arguments?.getLong("itemId") ?: 0L
                        DetailScreen(itemId = itemId)
                    }
                }
            }
        }
    }
}

يستخدم Navigation Compose مسارات نصية بدلاً من ids. تُمرر المعاملات عبر قوالب المسار ("detail/{itemId}") وتُستخرج من backStackEntry. rememberNavController() يحافظ على NavController عبر عمليات إعادة التركيب. لسلامة الأنواع في Compose، يُوصى بوحدة navigation-compose-type-safety (تجريبية).

الأسئلة الشائعة

ما هو NavHost في Navigation Component؟

NavHost هي حاوية لعرض شاشات التنقل. يتم تنفيذها عبر NavHostFragment في تخطيط XML. يتتبع NavHost الشاشة الحالية في NavGraph ويدير الانتقالات. كل Activity يحتوي على NavHostFragment واحد.

كيف Safe Args أفضل من Bundle؟

Safe Args هي إضافة Gradle تولد فئات وسائط آمنة الأنواع. Bundle يتطلب تحديد المفاتيح والأنواع يدوياً، مما يؤدي إلى أخطاء وقت التشغيل. Safe Args يتحقق من الأنواع في وقت الترجمة ويسلسل البيانات تلقائياً.

كيف نمرر كائنات معقدة عبر Navigation Component؟

تُمرر الكائنات المعقدة عبر ViewModel (مشترك بين الشاشات) أو عبر قاعدة البيانات بتمرير معرف. Safe Args يدعم فقط الأنواع البدائية والسلاسل و Parcelable. توصي Google بتجنب تمرير الكائنات الكبيرة عبر وسائط التنقل.

كيف يعمل Deep Link في Navigation Component؟

Deep Link يُضبط في NavGraph عبر السمة app:deepLink. يعالج Navigation Component الروابط الواردة تلقائياً، وينشئ PendingIntent عبر NavDeepLinkBuilder ويستعيد مكدس التنقل إلى الشاشة المستهدفة. يدعم URI و intent action ونوع mime.

هل يمكن استخدام Navigation Component مع Jetpack Compose؟

نعم. Navigation Compose (androidx.navigation:navigation-compose) يوفر NavHost لـ Compose. API مشابه لإصدار XML، لكن الشاشات هي دوال Composable. يستخدم NavController بنفس الطريقة في كلا الإصدارين. توصي Google بـ Navigation Compose للمشاريع الجديدة على Compose.

الخلاصة

  • Navigation Component — مكتبة Android Jetpack للتنقل المركزي مع NavController و NavHost و NavGraph
  • NavGraph — رسم بياني XML يصف جميع الشاشات (الوجهات) والاتصالات (الإجراءات) بينها
  • NavHostFragment — حاوية في تخطيط Activity تدعم السمة defaultNavHost لزر العودة
  • Safe Args — إضافة Gradle لتمرير الوسائط بأمان أنواعها مع التحقق في وقت الترجمة
  • الروابط العميقة تدعم URI و intent action ونوع mime مع استعادة تلقائية لمكدس التنقل
  • Navigation Compose — امتداد لـ Jetpack Compose بمسارات نصية وشاشات composable
  • Navigation Component هي الطريقة الوحيدة الموصى بها من Google للتنقل في مشاريع Android الجديدة

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا