Android--Jetpack--Navigation详解

须知少日拏云志,曾许人间第一流

一,定义

Navigation 翻译成中文就是导航的意思。它是谷歌推出的Jetpack的一员,其目的主要就是来管理页面的切换和导航。

Activity 嵌套多个 Fragment 的 UI 架构模式已经非常普遍,但是对 Fragment 的管理,我们一般通过 FragmentManager 和 FragmentTransaction 来管理 Fragment 之间的切换。页面的切换通常还包括对应用程序 App bar 的管理、Fragment 间的切换动画,以及 Fragment 间的参数传递。纯代码的方式使用起来不是特别友好,并且 Fragment 和 App bar 在管理和使用的过程中显得混乱。

使用Navigation可以很方便的管理和切换Fragment。

二,角色介绍

Navigation组件由三部分构成:

1)导航图(xml文件)包含所有导航相关信息的 XML 资源,其中包含所有目的地和操作。该图表会显示应用的所有导航路径。

2)NavHostFragment导航宿主是 Navigation 组件的核心部分之一。导航宿主是一个空容器,用户在应用中导航时,目的地会在该容器中交换进出。

3)NavController导航到目的地是使用NavController 完成的,它是一个在NavHost中管理应用导航的对象。每个NavHost均有自己的相应NavController 。

三,Navigation的优点

1)可视化的页面导航图,类似于 Apple Xcode 中的 StoryBoard,便于我们理清页面关系。

2)通过 destination 和 action 完成页面间的导航。

 3)方便添加页面切换动画。

 4)页面间类型安全的参数传递。

 5)通过 NavigationUI,对菜单、底部导航、抽屉菜单导航进行统一的管理。

四,基本使用

1,在app的build.gradle中添加引用:

implementation 'androidx.navigation:navigation-fragment:2.4.1'
implementation 'androidx.navigation:navigation-ui:2.4.1'

2,在res目录下创建导航图(xml文件):

 

 点击ok就会生成xml文件

3,创建fragment:

创建三个fragment,分别为YZ1Fragment,YZ2Fragment,YZ3Fragment

public class YZ1Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_yz1,container,false);
    }

}

fragment_yz1:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="#223355">

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="我是第一页"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="跳转第二页"
        android:textAllCaps="false"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/message" />

</androidx.constraintlayout.widget.ConstraintLayout>
public class YZ2Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_yz2,container,false);
    }
}

fragment_yz2:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="#dd2233">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="16dp"
        android:text="第二页"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:text="返回第一页"
        android:textAllCaps="false"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:text="前往第三页"
        android:textAllCaps="false"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn" />

</androidx.constraintlayout.widget.ConstraintLayout>
public class YZ3Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_yz3,container,false);
    }
}

fragment_yz3:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="#33ff22">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="16dp"
        android:text="第三页"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:text="跳到第二页"
        android:textAllCaps="false"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>

4,回到yuanzhen_nav.xml中,点击添加:

添加三个fragment :

然后收到添加跳转方向:

 

 就会自动生成代码:

<?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"
    android:id="@+id/yuanzhen_nav"
    app:startDestination="@id/YZ1Fragment">
    <fragment
        android:id="@+id/YZ1Fragment"
        android:name="com.yuanzhen.mynavigation.YZ1Fragment"
        android:label="YZ1Fragment" >
        <action
            android:id="@+id/action_YZ1Fragment_to_YZ2Fragment2"
            app:destination="@id/YZ2Fragment" />
    </fragment>
    <fragment
        android:id="@+id/YZ2Fragment"
        android:name="com.yuanzhen.mynavigation.YZ2Fragment"
        android:label="YZ2Fragment" >
        <action
            android:id="@+id/action_YZ2Fragment_to_YZ3Fragment2"
            app:destination="@id/YZ3Fragment" />
        <action
            android:id="@+id/action_YZ2Fragment_to_YZ1Fragment2"
            app:destination="@id/YZ1Fragment" />
    </fragment>
    <fragment
        android:id="@+id/YZ3Fragment"
        android:name="com.yuanzhen.mynavigation.YZ3Fragment"
        android:label="YZ3Fragment" >
        <action
            android:id="@+id/action_YZ3Fragment_to_YZ2Fragment2"
            app:destination="@id/YZ2Fragment" />
    </fragment>
</navigation>

这里的action代表的就是跳转路径。

5,在fragment中实现跳转代码:

public class YZ1Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_yz1,container,false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button btn=view.findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Navigation.findNavController(view).navigate(R.id.action_YZ1Fragment_to_YZ2Fragment2);
            }
        });
    }

}
public class YZ2Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_yz2,container,false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button btn=view.findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Navigation.findNavController(view).navigate(R.id.action_YZ2Fragment_to_YZ1Fragment2);
            }
        });

        Button btn2=view.findViewById(R.id.btn2);
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Navigation.findNavController(view).navigate(R.id.action_YZ2Fragment_to_YZ3Fragment2);
            }
        });
    }
}
public class YZ3Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_yz3,container,false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button btn=view.findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Navigation.findNavController(view).navigate(R.id.action_YZ3Fragment_to_YZ2Fragment2);
            }
        });
    }

}

6,在Activity添加fragment:

public class MainActivity extends AppCompatActivity {
    private NavController navController;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        navController = Navigation.findNavController(this, R.id.frag);
        NavigationUI.setupActionBarWithNavController(this, navController);

    }


}

activity_main:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

运行效果:

 五,添加导航栏

1,在res目录下添加menu:

2,menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/YZ1Fragment"
        android:icon="@mipmap/pic_article_default"
        android:title="首页"/>
    <item
        android:id="@+id/YZ2Fragment"
        android:icon="@mipmap/tell_normal"
        android:title="第二页"/>
    <item
        android:id="@+id/YZ3Fragment"
        android:icon="@mipmap/video_call_default"
        android:title="第三页"/>
</menu>

注意,这里的id就是你要跳转的fragment名称

3,在activity_main添加新的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <fragment
        android:id="@+id/frag"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="9"
        app:defaultNavHost="true"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/yuanzhen_nav"/>
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/btm"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        app:menu="@menu/menu"/>

</LinearLayout>

4,在MainActivity添加代码:

public class MainActivity extends AppCompatActivity {
    private NavController navController;
    BottomNavigationView bottomNavigationView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bottomNavigationView=findViewById(R.id.btm);
        navController = Navigation.findNavController(this, R.id.frag);
        NavigationUI.setupWithNavController(bottomNavigationView,navController);
    }
}

实现效果:

 六,添加动画效果

添加动画效果非常简单:

1,打开yuanzhen_nav.xml文件

2,点击试图的跳转线:

3, 

有四个动画可以选择

选择之后yaunzhen_nav文件如下:

<?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"
    android:id="@+id/yuanzhen_nav"
    app:startDestination="@id/YZ1Fragment">
    <fragment
        android:id="@+id/YZ1Fragment"
        android:name="com.yuanzhen.mynavigation.YZ1Fragment"
        android:label="YZ1Fragment" >
        <action
            android:id="@+id/action_YZ1Fragment_to_YZ2Fragment2"
            app:destination="@id/YZ2Fragment"
            app:enterAnim="@anim/nav_default_pop_enter_anim"
            app:exitAnim="@anim/nav_default_pop_enter_anim"
            app:popEnterAnim="@anim/nav_default_pop_exit_anim"
            app:popExitAnim="@anim/nav_default_pop_exit_anim" />
    </fragment>
    <fragment
        android:id="@+id/YZ2Fragment"
        android:name="com.yuanzhen.mynavigation.YZ2Fragment"
        android:label="YZ2Fragment" >
        <action
            android:id="@+id/action_YZ2Fragment_to_YZ3Fragment2"
            app:destination="@id/YZ3Fragment"
            app:enterAnim="@anim/nav_default_enter_anim"
            app:exitAnim="@anim/nav_default_exit_anim"
            app:popEnterAnim="@anim/nav_default_enter_anim"
            app:popExitAnim="@anim/nav_default_pop_exit_anim" />
        <action
            android:id="@+id/action_YZ2Fragment_to_YZ1Fragment2"
            app:destination="@id/YZ1Fragment" />
    </fragment>
    <fragment
        android:id="@+id/YZ3Fragment"
        android:name="com.yuanzhen.mynavigation.YZ3Fragment"
        android:label="YZ3Fragment" >
        <action
            android:id="@+id/action_YZ3Fragment_to_YZ2Fragment2"
            app:destination="@id/YZ2Fragment" />
    </fragment>
</navigation>

也可以自己去自定义动画

  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

袁震

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值