Navigation of Jetpack's Architecture Components

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28898075/article/details/88124403

 

前言

Navigation 是应用程序设计的重要组成部分。 通过Navigation ,可以设计允许用户在应用内的不同内容区域中移动,移入和移出的交互。说白了其实是用来管理 APP 里页面跳转的。

使用

如果您想使用Android Studio导航,则必须使用Android Studio 3.3或更高版本。

要向项目添加导航图,请执行以下操作:

  1. 在“项目”窗口中,右键单击res目录,然后选择“ New > Android Resource File。 出现 New Resource File 对话框。

  2. 在“文件名”字段中键入名称,例如“nav_graph”。

  3. 从 Resource type下拉列表中选择Navigation

  4. 单击确定。 发生以下情况:

    ​ 在res目录中创建navigation资源目录。
    ​ 在navigation目录中创建nav_graph.xml文件。
    ​ nav_graph.xml文件在导航编辑器中打开。 此XML文件包含导航图。

  5. 单击 Text选项卡以切换到XML文本视图。 您应该看到一个空的导航图,如以下示例所示:

    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:android="http://schemas.android.com/apk/res/android">
    </navigation>
    
  6. 单击Design 返回“导航编辑器”。

创建destinations

  1. 在导航栏编辑器中, 点击New Destinationimg, 然后点击 Create blank destination.
  2. New Android Component 弹窗出现, 输入一个Fragment Name.作为 Fragment类的名字
  3. 要让Android Studio为Fragment创建相应的布局资源文件,请选中Create layout XML旁边的框,然后在Fragment Layout Name字段中输入资源名称。
  4. 在 Source Language 下拉框中为类源文件选择 Kotlin 或者 Java 语言。
  5. 点击Finish.

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/blankFragment">
    <fragment
        android:id="@+id/blankFragment"
        android:name="com.example.cashdog.cashdog.BlankFragment"
        android:label="fragment_blank"
        tools:layout="@layout/fragment_blank" />
    <fragment
        android:id="@+id/blankFragment2"
        android:name="com.example.cashdog.cashdog.BlankFragment2"
        android:label="Blank2"
        tools:layout="@layout/fragment_blank_fragment2" />
</navigation>

连接destinations

使用action连接两个destinations,如下所示:

在“设计”选项卡中,将鼠标悬停在您希望用户导航的目标的右侧。目的地上会出现一个圆圈。单击并按住,将光标拖到希望用户导航到的目标上,然后释放。绘制一条线以指示两个目的地之间的导航。相应的会生成xml代码

<?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/blankFragment">
    <fragment
        android:id="@+id/blankFragment"
        android:name="com.example.cashdog.cashdog.BlankFragment"
        android:label="fragment_blank"
        tools:layout="@layout/fragment_blank" >
        <action
            android:id="@+id/action_blankFragment_to_blankFragment2"
            app:destination="@id/blankFragment2" />
    </fragment>
    <fragment
        android:id="@+id/blankFragment2"
        android:name="com.example.cashdog.cashdog.BlankFragment2"
        android:label="fragment_blank_fragment2"
        tools:layout="@layout/fragment_blank_fragment2" />
</navigation>

在谷歌官方demo中,实现了一组fragment之间的关系,在action中可以设置转场动画

<?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"
            app:startDestination="@id/title_screen">
    <fragment
        android:id="@+id/title_screen"
        android:name="com.example.android.navigationsample.TitleScreen"
        android:label="fragment_title_screen"
        tools:layout="@layout/fragment_title_screen">
        <action
            android:id="@+id/action_title_screen_to_register"
            app:destination="@id/register"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
        <action
            android:id="@+id/action_title_screen_to_leaderboard"
            app:destination="@id/leaderboard"
            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/register"
        android:name="com.example.android.navigationsample.Register"
        android:label="fragment_register"
        tools:layout="@layout/fragment_register">
        <action
            android:id="@+id/action_register_to_match"
            app:destination="@id/match"
            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/leaderboard"
            android:name="com.example.android.navigationsample.Leaderboard"
            android:label="fragment_leaderboard"
            tools:layout="@layout/fragment_leaderboard">
        <action
                android:id="@+id/action_leaderboard_to_userProfile"
                app:destination="@id/user_profile"
                app:popEnterAnim="@anim/slide_in_left"
                app:popExitAnim="@anim/slide_out_right"
                app:enterAnim="@anim/slide_in_right"
                app:exitAnim="@anim/slide_out_left"/>
    </fragment>
    <fragment
            android:id="@+id/match"
            android:name="com.example.android.navigationsample.Match"
            android:label="fragment_match"
            tools:layout="@layout/fragment_match">
        <action
                android:id="@+id/action_match_to_in_game"
                app:destination="@id/in_game"
                app:popEnterAnim="@anim/slide_in_left"
                app:popExitAnim="@anim/slide_out_right"
                app:enterAnim="@anim/slide_in_right"
                app:exitAnim="@anim/slide_out_left"/>
    </fragment>
    <fragment
            android:id="@+id/user_profile"
            android:name="com.example.android.navigationsample.UserProfile"
            android:label="fragment_user_profile"
            tools:layout="@layout/fragment_user_profile">
        <argument android:name="userName"
                  android:defaultValue="name"/>
        <deepLink app:uri="www.example.com/user/{userName}" />
    </fragment>
    <fragment
            android:id="@+id/in_game"
            android:name="com.example.android.navigationsample.InGame"
            android:label="Game"
            tools:layout="@layout/fragment_in_game">
        <action
                android:id="@+id/action_in_game_to_resultsWinner"
                app:destination="@id/results_winner"
                app:popUpTo="@+id/match"
                app:popUpToInclusive="false"
                app:popEnterAnim="@anim/slide_in_left"
                app:popExitAnim="@anim/slide_out_right"
                app:enterAnim="@anim/fade_in"
                app:exitAnim="@anim/fade_out"/>
        <action
                android:id="@+id/action_in_game_to_gameOver"
                app:destination="@id/game_over"
                app:popUpTo="@id/match"
                app:popUpToInclusive="false"
                app:popEnterAnim="@anim/slide_in_left"
                app:popExitAnim="@anim/slide_out_right"
                app:enterAnim="@anim/fade_in"
                app:exitAnim="@anim/fade_out"/>
    </fragment>
    <fragment
            android:id="@+id/results_winner"
            android:name="com.example.android.navigationsample.ResultsWinner"
            tools:layout="@layout/fragment_results_winner">
        <action android:id="@+id/action_results_winner_to_leaderboard"
                app:destination="@id/leaderboard"
                app:popUpTo="@id/title_screen"/>
        <action android:id="@+id/action_results_winner_to_match"
                app:popUpTo="@id/match"/>
        <action
            android:id="@+id/action_results_winner_to_match2"
            app:destination="@id/match" />
    </fragment>
    <fragment
            android:id="@+id/game_over"
            android:name="com.example.android.navigationsample.GameOver"
            android:label="fragment_game_over"
            tools:layout="@layout/fragment_game_over">
        <action android:id="@+id/action_game_over_to_match"
                app:popUpTo="@id/match"/>
    </fragment>

</navigation>

修改Activity支持导航

activity为NavHost中的应用程序提供导航。 NavHost是一个当用户浏览您的应用程序时,目的地会被换入和换出空容器。

NavHost是一个接口,Navigation组件的默认NavHost实现是NavHostFragment。

xml实现

<FrameLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/background_light"
    tools:context="com.example.android.navigationsample.MainActivity">

    <fragment
            android:id="@+id/my_nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/navigation"/>
</FrameLayout>

navGraph 属性就是写刚才我们写的 nagation 文件

app:defaultNavHost =“true” 属性可确保NavHostFragment拦截系统“后退”按钮。 还可以通过覆盖AppCompatActivity.onSupportNavigateUp()并调用NavController.navigateUp来实现此行为,如下例所示:

@Override
public boolean onSupportNavigateUp() {
    return Navigation.findNavController(this, R.id.nav_host_fragment).navigateUp();
}

当然也可以代码实现

NavHostFragment finalHost = NavHostFragment.create(R.navigation.example_graph);
getSupportFragmentManager().beginTransaction()
    .replace(R.id.nav_host, finalHost)
    .setPrimaryNavigationFragment(finalHost) // this is the equivalent to app:defaultNavHost="true"
    .commit();

界面跳转

使用NavController类导航到目标。 可以使用以下静态方法之一检索NavController

NavHostFragment.findNavController(Fragment)
Navigation.findNavController(Activity, @IdRes int viewId)
Navigation.findNavController(View)

拿到NavController后,使用其navigate()方法导航到目标。 navigate()方法接受资源ID。 ID可以是导航图的destination 或action中特定目标的ID。

  view.findViewById<Button>(R.id.play_btn).setOnClickListener {
            Navigation.findNavController(view).navigate(R.id.action_title_screen_to_register)
        }
        view.findViewById<Button>(R.id.leaderboard_btn).setOnClickListener {
            Navigation.findNavController(view).navigate(R.id.action_title_screen_to_leaderboard)
        }

猜你喜欢

转载自blog.csdn.net/qq_28898075/article/details/88124403