گراف‌های تودرتو

جریان‌های ورود به سیستم، جادوگرها، یا سایر جریان‌های فرعی در برنامه شما معمولاً بهتر است به‌عنوان نمودارهای پیمایش تودرتو نمایش داده شوند. با قرار دادن جریان‌های فرعی ناوبری مستقل به این روش، درک و مدیریت جریان اصلی واسط کاربر برنامه شما آسان‌تر می‌شود.

علاوه‌براین، نمودارهای تودرتو قابل‌استفاده مجدد هستند. آن‌ها همچنین سطحی از کپسوله‌سازی را ارائه می‌دهند—مقصدهای خارج از نمودار تودرتو دسترسی مستقیم به هیچ‌یک از مقصدهای داخل نمودار تودرتو ندارند. درعوض، باید navigate() به خود نمودار تودرتو، جایی که منطق داخلی می‌تواند بدون تأثیر بر بقیه نمودار تغییر کند.

مثال

نمودار پیمایش سطح بالای برنامه شما باید با مقصد اولیه‌ای که کاربر هنگام راه‌اندازی برنامه می‌بیند شروع شود و باید شامل مقصدهایی باشد که کاربر هنگام حرکت در برنامه شما می‌بیند.

شکل ۱. گراف پیمایش سطح بالا.

بااستفاده از نمودار پیمایش سطح بالا از شکل ۱ به‌عنوان نمونه، فرض کنید می‌خواهید کاربر را ملزم کنید که صفحه‌های title_screen و register را فقط هنگام راه‌اندازی برنامه برای اولین‌بار ببیند. پس‌از آن، اطلاعات کاربر ذخیره می‌شود و در دفعات بعدی که برنامه راه‌اندازی می‌شود، باید کاربر را مستقیماً به صفحه تطابق هدایت کنید.

به‌عنوان روال مطلوب، صفحه مطابقت را به‌عنوان مقصد شروع نمودار پیمایش سطح بالا تنظیم کنید و صفحه‌های عنوان و ثبت را به نمودار تودرتو منتقل کنید، همان‌طور که در شکل ۱ نشان داده شده است:

شکل ۲. گراف پیمایش سطح بالا اکنون حاوی گراف تودرتو است.

وقتی صفحه تطابق راه‌اندازی می‌شود، بررسی کنید تا ببینید آیا کاربر ثبت‌شده‌ای وجود دارد یا نه. اگر کاربر ثبت‌نام نکرده است، کاربر را به صفحه ثبت‌نام هدایت کنید.

برای اطلاعات بیشتر درباره سناریوهای ناوبری شرطی، به ناوبری شرطی مراجعه کنید.

نوشتن

برای ایجاد نمودار ناوبری تودرتو بااستفاده از Compose، از تابع NavGraphBuilder.navigation() استفاده کنید. هنگام افزودن مقصدها به نمودار، از navigation() درست مانند توابع NavGraphBuilder.composable() و NavGraphBuilder.dialog() استفاده می‌کنید.

تفاوت اصلی این است که navigation به‌جای مقصد جدید، نمودار تودرتو ایجاد می‌کند. سپس composable() و dialog() را در لامبدای navigation() فراخوانی می‌کنید تا مقصدها را به نمودار تودرتو اضافه کنید.

ببینید قطعه کد زیر چگونه نمودار شکل ۲ را بااستفاده از Compose پیاده‌سازی می‌کند:

// Routes
@Serializable object Title
@Serializable object Register

// Route for nested graph
@Serializable object Game

// Routes inside nested graph
@Serializable object Match
@Serializable object InGame
@Serializable object ResultsWinner
@Serializable object GameOver

NavHost(navController, startDestination = Title) {
   composable<Title> {
       TitleScreen(
           onPlayClicked = { navController.navigate(route = Register) },
           onLeaderboardsClicked = { /* Navigate to leaderboards */ }
       )
   }
   composable<Register> {
       RegisterScreen(
           onSignUpComplete = { navController.navigate(route = Game) }
       )
   }
   navigation<Game>(startDestination = Match) {
       composable<Match> {
           MatchScreen(
               onStartGame = { navController.navigate(route = InGame) }
           )
       }
       composable<InGame> {
           InGameScreen(
               onGameWin = { navController.navigate(route = ResultsWinner) },
               onGameLose = { navController.navigate(route = GameOver) }
           )
       }
       composable<ResultsWinner> {
           ResultsWinnerScreen(
               onNextMatchClicked = {
                   navController.navigate(route = Match) {
                       popUpTo(route = Match) { inclusive = true }
                   }
               },
               onLeaderboardsClicked = { /* Navigate to leaderboards */ }
           )
       }
       composable<GameOver> {
           GameOverScreen(
               onTryAgainClicked = {
                   navController.navigate(route = Match) {
                       popUpTo(route = Match) { inclusive = true }
                   }
               }
           )
       }
   }
}

برای پیمایش مستقیم به مقصد تودرتو، از نوع مسیر استفاده کنید، همان‌طور که برای هر مقصد دیگری استفاده می‌کنید. دلیلش این است که مسیرها مفهومی جهانی هستند که برای شناسایی مقصدهایی استفاده می‌شوند که هر صفحه‌ای می‌تواند به آن‌ها پیمایش کند:

navController.navigate(route = Match)
مراجعه کنید

XML

هنگام استفاده از XML، می‌توانید از «ویرایشگر پیمایش» برای ایجاد نمودار تودرتو استفاده کنید. برای انجام این کار، این مراحل را دنبال کنید:

  1. در Navigation Editor (ویرایشگر پیمایش)، کلید Shift را فشار دهید و نگه دارید، و روی مقصدهایی که می‌خواهید در نمودار تودرتو گنجانده شود کلیک کنید.
  2. کلیک راست کنید تا منوِ زمینه‌ای باز شود، سپس انتقال به نمودار تودرتو > نمودار جدید را انتخاب کنید. مقصدها در نمودار تودرتو قرار دارند. شکل ۲ نمودار تودرتو را در ویرایشگر پیمایش نشان می‌دهد:

    شکل ۲. گراف تودرتو در «ویرایشگر پیمایش»
  3. روی نمودار تودرتو کلیک کنید. مشخصه‌های زیر در پانل مشخصه‌ها نشان داده می‌شود:

    • نوع، که حاوی «نمودار تودرتو» است
    • شناسه، که حاوی شناسه اختصاص‌داده‌شده توسط سیستم برای نمودار تودرتو است. از این شناسه برای ارجاع به نمودار تودرتو از کدتان استفاده می‌شود.
  4. روی نمودار تودرتو دوکلیک کنید تا مقصدهای آن نشان داده شود.

  5. روی برگه نوشتار کلیک کنید تا به نمای XML بروید. نمودار پیمایش تودرتو به نمودار اضافه شده است. این نمودار ناوبری عناصر navigation خودش را به‌همراه شناسه خودش و مشخصه startDestination دارد که به اولین مقصد در نمودار تودرتو اشاره می‌کند:

    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:app="http://schemas.android.com/apk/res-auto"
       xmlns:tools="http://schemas.android.com/tools"
       xmlns:android="http://schemas.android.com/apk/res/android"
       app:startDestination="@id/mainFragment">
       <fragment
           android:id="@+id/mainFragment"
           android:name="com.example.cashdog.cashdog.MainFragment"
           android:label="fragment_main"
           tools:layout="@layout/fragment_main" >
           <action
               android:id="@+id/action_mainFragment_to_sendMoneyGraph"
               app:destination="@id/sendMoneyGraph" />
           <action
               android:id="@+id/action_mainFragment_to_viewBalanceFragment"
               app:destination="@id/viewBalanceFragment" />
       </fragment>
       <fragment
           android:id="@+id/viewBalanceFragment"
           android:name="com.example.cashdog.cashdog.ViewBalanceFragment"
           android:label="fragment_view_balance"
           tools:layout="@layout/fragment_view_balance" />
       <navigation android:id="@+id/sendMoneyGraph" app:startDestination="@id/chooseRecipient">
           <fragment
               android:id="@+id/chooseRecipient"
               android:name="com.example.cashdog.cashdog.ChooseRecipient"
               android:label="fragment_choose_recipient"
               tools:layout="@layout/fragment_choose_recipient">
               <action
                   android:id="@+id/action_chooseRecipient_to_chooseAmountFragment"
                   app:destination="@id/chooseAmountFragment" />
           </fragment>
           <fragment
               android:id="@+id/chooseAmountFragment"
               android:name="com.example.cashdog.cashdog.ChooseAmountFragment"
               android:label="fragment_choose_amount"
               tools:layout="@layout/fragment_choose_amount" />
       </navigation>
    </navigation>
    
  6. در کدتان، شناسه منبع کنش متصل‌کننده گراف ریشه به گراف تودرتو را ارسال کنید:

کاتلین

view.findNavController().navigate(R.id.action_mainFragment_to_sendMoneyGraph)

جاوا

Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
  1. در برگه طراحی، با کلیک کردن روی ریشه به نمودار ریشه برگردید.

ارجاع به نمودارهای ناوبری دیگر با include

روش دیگر برای مدولار کردن ساختار نمودار شما این است که بااستفاده از عنصر <include> در نمودار پیمایش اصلی، یک نمودار را در نمودار دیگر بگنجانید. این کار اجازه می‌دهد نمودار گنجانده‌شده در یک واحد یا پروژه کاملاً جداگانه تعریف شود که قابلیت استفاده مجدد را به حداکثر می‌رساند.

تکه‌کد زیر نشان می‌دهد که چگونه می‌توانید از <include> استفاده کنید:

<!-- (root) nav_graph.xml -->
<?xml version="1.0" encoding="utf-8"?>
<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"
    android:id="@+id/nav_graph"
    app:startDestination="@id/fragment">

    <include app:graph="@navigation/included_graph" />

    <fragment
        android:id="@+id/fragment"
        android:name="com.example.myapplication.BlankFragment"
        android:label="Fragment in Root Graph"
        tools:layout="@layout/fragment_blank">
        <action
            android:id="@+id/action_fragment_to_second_graph"
            app:destination="@id/second_graph" />
    </fragment>

    ...
</navigation>
<!-- included_graph.xml -->
<?xml version="1.0" encoding="utf-8"?>
<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"
    android:id="@+id/second_graph"
    app:startDestination="@id/includedStart">

    <fragment
        android:id="@+id/includedStart"
        android:name="com.example.myapplication.IncludedStart"
        android:label="fragment_included_start"
        tools:layout="@layout/fragment_included_start" />
</navigation>