Android Navigation 详解

一、导航概述

    Navigation 用于 Fragment 的管理。他可以让 Fragrant 之间的切换,拥有像 Activity 间一样的跳转。与 DrawerLayout(抽屉式布局)、ActionBar(导航栏)等有简洁完美的对接。

二、开发环境设置

注意:Navigation 需要在 Android Studio 3.3 或更高版本中才可使用。(并且在 androidx 中支持的更好,之前没有使用 androidx 一直无法添加 Fragment 目的地)

若要在项目中包含导航支持,请将以下依赖项添加到应用程序的 build.gradle 文件中:

dependencies {
  def nav_version = "2.1.0-rc01"

  // Java
  implementation "androidx.navigation:navigation-fragment:$nav_version"
  implementation "androidx.navigation:navigation-ui:$nav_version"

  // Kotlin
  implementation "androidx.navigation:navigation-fragment-ktx:$nav_dep"
  implementation "androidx.navigation:navigation-ui-ktx:$nav_dep"

}

三、创建 navigation graph (导航图)

  导航图是一个 XML 资源文件,在导航图中有两个概念:

    1.Destination:导航图中的每一个导航被称为 Destination (目的地)。

    2.Action:导航与导航之间使用 Action (事件) 连接,用于说明两个导航之间的跳转关系。

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

    在项目的 res 目录下,新建一个 navigation 文件夹,右键 navigation 文件夹,依次选择:NewNavigation resource file

Android Navigation 详解_第1张图片

    填写文件名称,如:nav_graph,点击 OK。

Android Navigation 详解_第2张图片

四、编辑导航图

    在编辑导航图前,需要先创建 Activity,与相关的 Fragment。(此处使用 1 个 Activity,三个 Fragment)

/**
 * @Author: Eli Shaw
 * @Date: 2019-08-18 10:10:42
 * @Description: Activity 容器类
 */
class NavigationActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_navigation)
    }
}
/**
 * @Author: Eli Shaw
 * @Date: 2019-08-18 10:07:13
 * @Description: 登录页
 */
class LoginFragment : Fragment(), View.OnClickListener {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val viewRoot = inflater.inflate(R.layout.fragment_login, container, false)
        return viewRoot
    }
}
/**
 * @Author: Eli Shaw
 * @Date: 2019-08-18 10:08:52
 * @Description: 注册页
 */
class RegisterFragment : Fragment(), View.OnClickListener {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val viewRoot = inflater.inflate(R.layout.fragment_register, container, false)
        return viewRoot
    }
}
/**
 * @Author: Eli Shaw
 * @Date: 2019-08-18 10:40:42
 * @Description: 首页
 */
class HomeFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home, container, false)
    }
}

    创建好 nav_graph 导航图后,双击进行编辑(与常规布局文件很相似)

Android Navigation 详解_第3张图片

1、指定 Activity 容器

    在 Activity 布局文件中指定导航图的容器



    

    android:name:指定 Fragment 的类型为 NavHostFragment。

    app:defaultNavHost="true":让 Navigation 容器处理返回事件,在 Navigation 容器中如果有页面的跳转,点击返回按钮会先处理 容器中 Fragment 页面间的返回,处理完容器中的页面,再处理 Activity 页面的返回。如果值为 false 则直接处理 Activity 页面的返回。

    app:navGraph:指定 Navigation 文件。

2、添加 Action (事件)

Android Navigation 详解_第4张图片

    拖动选中的(目的地)右方的圆点到另一个(目的地)即可创建一个 Action(事件)。

    点击左下角的 Text ,将显示如下代码



    
    
        
        
    

    
    
        
    

    
    

3、导航图的复用

    是导航图的根元素,Destination (目的地) 与 Action (事件) 都是 元素中的节点。

     中可以包含  节点,这样使用的目的是可以复用相同的导航图。例如:增加一个找回密码页,这个找回密码页在另一个导航图中,找回密码后再继续登录操作:

Android Navigation 详解_第5张图片

    此图是一个包含导航图的预览页,文本内容如下



    
        
    

    
    

五、导航图间的跳转

1、获取 NavController 的方式

    导航图使用 NavController 控制(目的地)之间的跳转,在 Activity,Fragment 中获取 NavController 有以下 6 种方式:

1.Fragment.findNavController()
2.View.findNavController()
3.Activity.findNavController(viewId: Int) //只有 Activity 中可以使用
4.NavHostFragment.findNavController(Fragment)
5.Navigation.findNavController(Activity, @IdRes int viewId) //只有 Activity 中可以使用
6.Navigation.findNavController(View)

2、导航中目的地间的传值

    导航中目的地间也可以使用 Bundle 进行传值

//使用 bundle 传值
val bundle = Bundle()
bundle.putInt(ARG_NAV, navController)

findNavController().navigate(R.id.actionLoginToRegister, bundle)

下面是登录页、注册页完整代码

private const val ARG_NAV = "nav"

/**
 * @Author: Eli Shaw
 * @Date: 2019-08-18 10:07:13
 * @Description: 登录页
 */
class LoginFragment : Fragment(), View.OnClickListener {

    private var navController: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            navController = it.getInt(ARG_NAV)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val viewRoot = inflater.inflate(R.layout.fragment_login, container, false)
        //注册点击事件
        viewRoot.findViewById
private const val ARG_NAV = "nav"

/**
 * @Author: Eli Shaw
 * @Date: 2019-08-18 10:08:52
 * @Description: 注册页
 */
class RegisterFragment : Fragment(), View.OnClickListener {

    private var navController: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            navController = it.getInt(ARG_NAV)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val viewRoot = inflater.inflate(R.layout.fragment_register, container, false)
        viewRoot.findViewById

3、导航中目的地间的转场动画

自定义转场动画

cut_to_enter.xml (入场动画)


    

cut_to_exit.xml(出场动画)


    

在导航图中编辑

Android Navigation 详解_第6张图片

你可能感兴趣的:(Android基础)