【译】Android Jetpack 架构导航组件之Navigation

示例代码:android-navigation
介绍:Navigation Codelab
原文:navigation-implementing

导航架构组件简化了App内不同目标的导航实现。一个目标即是App内一个特定的屏幕。导航架构组件默认包含了对fragments和Activities的支持,但是你也可以添加对新类型目标的支持。一系列的目标集合组成了app的导航图。

另外,导航图内不同目标的连接被称作"actions"。图1展示了示例app内一个假设的导航图表现,包含了6个目标,由5个actions连接。

【译】Android Jetpack 架构导航组件之Navigation_第1张图片
图1 navigation-graph.png

导航架构组件是基于Principles of nagivation实现的。

Set up nagivation in a project

在你创建一个导航图之前,你必须在你的工程内配置导航架构组件。以下是具体步骤:

  1. 在你的app或者模块的build.gradle文件内天井Navigation Architecture Component。点击Adding components to your project查看更多。
  2. 在工程窗口,右击 res 目录,选择 New > Android resource file。显示New Resource对话框。
  3. 输入资源名称在File name栏目,比如“nav_graph”。
  4. 选择NavigationResource type下拉列表。
  5. 点击 OK。出现以下项目:
    a. 一个 nagivation 资源目录在res目录下创建。
    b. 一个nav_graph.xml文件在navigation目录下创建。
    c. nav_graph.xml文件将在Navigation Editor中打开。这个文件包含了你的导航图。
  6. 点击Texttab可以打开或者关闭text View。空导航图如下:

  1. 点击 Design返回导航编辑器。

Tour The Navigation Editor

Note: The Navigation Editor是在Android Studio的Canary Build中默认开启的。为了在Beta,Release Candidate和Stable Builds 中启用,在Mac上点击File > Settings(Android Studio > Preferences),在左侧面板选择Experimentalcategory,选择Enable Navigation Editor,最后重启Android Studio。

【译】Android Jetpack 架构导航组件之Navigation_第2张图片
图2 navigation-editor.png

在导航编辑器,你可以快速地构建导航图,不需要手动构建graph’s xml文件。按照图2显示的,导航编辑器分为三个部分。
1. 目标列表-罗列当前导航编辑器内所有目标。
2. 图编辑器-包含导航图内所有虚拟目标。
3. 属性编辑器-包含目标属性和导航图内的actions。

Identify destinations

为你的app验证目标是创建导航图的第一部。你可以创建一个空目标或者在一个已经存在的工程内为fragments和Acitvities创建目标。

Note:导航架构组件是为一个activity内包含多个fragment的场景而设计的。主activity拥有导航图。在一个拥有众多activity目标的app内,每一个附加的activity都拥有自己的导航图。修改一个activity到主导航将在之后的文档进行讨论。

请参照一下步骤验证app内目标:

  1. 在图编辑器,点击** New DestinationNew Destination** 显示。
  2. 点击Create blank destination或者点击一个fragment或者activity。会出现新的Android Component 对话框。
  3. Fragment Name字段输入名字。这个名字是fragment的类的名字。
  4. Fragment layout Name字段输入一个名字。这个名字是fragment布局文件的名字。
  5. 点击完成,在图标编辑器的目标列表出现一个目标,出现以下现象:
  • 如果你创建一个空白的目标,在图标编辑器出现一个空白的一个“Hello blank fragment” 的信息的目标,如果你点击了一个Fragment或者Activity,图标编辑器会显示对应的布局。
  • 一个fragment子类将会被创建,名字在第三步被指定。
  • 一个资源文件会被创建,名字在第四步被指定。

图3 展示了一个空白的已经存在的目标。


【译】Android Jetpack 架构导航组件之Navigation_第3张图片
图3 navigation-newexisting.png
  1. 点击高亮显示新插入的目标。在属性面板显示以下属性。
  • 在类型字段显示“fragment”或者“activity”,表示目标是否执行了fragment或者activity。
  • 标签字段表示了目标布局文件的名字;
  • ID字段表示了目标的ID,用来在代码中被引用;
  • 类字段表示了引用的目标的类名;
  1. 点击Text 进入xml视图,XML现在包含id,name(class name),label和layout属性,基于已经存在的类和布局文件的名字。


    

Note:XML布局startDestination 表示一个空目标的Id,(app:startDestination="@+id/fragment")。查询更多关于startDestination信息请点击 Designate a screen as the start destination。

Connect destinations



    
    

通过action连接不同的destination:
1、在Graph Editor,当鼠标浮动在destination的右边缘时会显示一个圈;
2、点击并且拖动圆圈到另一个destination,一条线将会关联起两个destination;


【译】Android Jetpack 架构导航组件之Navigation_第4张图片
图5navigation-connected.png

3、点击高亮箭头,属性面板显示以下属性:

  • 类型字段包含“Action”;
  • ID字段表示了系统为action指定的ID;
  • Destination字段表示了目标Activity或者Fragment;
    4、代码展示:


    
        
    
    

Designate a screen as the start destination

Graph Editor中,进入app的第一个Destination会有一个house的icon。通过一下步骤可以将另外一个Destination指定为启动Destination。
1、点击高亮显示某个Destination;
2、点击属性面板的Set Start Destination即可完成设置;

Modify an activity to host navigation

一个Activity通过NavHost的实现类来持有app的导航。NavHost是一个空的View,因此Destinations会根据用户的导航被交换进或者退出。
Navigation Architecture Component 的默认的NavHost的实现是NavHostFragment。
在你包含了NavHost之后,你必须使用navGraph属性将NavHostFragment和Navigation graph关联起来。下面是代码示例:




    


上述例子的app:defaultNavHost="true"属性可以确保NavHostFragment可以拦截系统的回退事件。你也可以重写AppCompatActivity.onSupportNavigateUp()方法并且调用NavController.navigateUp方法:

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

Create the NavHostFragment programmatically

你可以使用NavHostFragment.create()
编码创建NavHostFragment ,关联一个graph资源,如下所示:

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();

Tie destinations to UI widgets

通过NavController
实现对Destination的导航。通过以下静态方法获取NavController示例:

  • NavHostFragment.findNavController(Fragment)
  • Navigation.findNavController(Activity, @IdRes int viewId)
  • Navigation.findNavController(View)
    通过 NavControllernavigate()
    方法导航到destination。navigate()
    方法接受一个资源Id的参数。该Id可以是一个特别的destination的Id或者是action Id。相比destination的Id,使用action Id可以使用关联的transition动画。点击Create a transition between destinations查询更多关于transition信息。
    以下代码示例展示了ViewTransactionsFragment的导航:
viewTransactionsButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Navigation.findNavController(view).navigate(R.id.viewTransactionsAction);
    }
});

Android 系统维护了一个back stack来表示最近访问的destination。
在app启动得时候,第一个destination会被放入栈里面。每一次调用navigate()
都会放入另外一个destination在栈的顶部。相反的,调用NavController.navigateUp()
NavController.popBackStack()
方法,从栈里弹出顶部的destination。对于按钮,你可以使用Navigation
类的 createNavigateOnClickListener() 方法来很方便地去导航到destination。

button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.next_fragment, null));

Tie destinations to menu-driven UI components

通过为destination、navigation drawer和overflow menu设置相同的Id来将destination和navigation drawer或者overflow menu关联起来。以下代码片段显示了id为details_page_fragment的destination:


以下代码片段表示了如何关联fragment destination 和navigation drawer中的menu item,比如( menu_nav_drawer.xml)。


以下XML表示了如果把destination和overflow menu 关联的细节:


Navigation Architecture Component 包含了一个NavigationUI
类。这个类的多个静态方法都可以用来关联 menu item 和 navigation destination。以下代码表示了如果使用setupWithNavController()
方法去关联 menu item 到Navigation View。

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
NavigationUI.setupWithNavController(navigationView, navController);

使用NavigationUI
去设置menu 驱动的导航组件是很有必要的,因为这样可以同步这些UI元素地改变到NavController。

Pass data between destinations

两种方式在不同的destination之间传递数据:使用Bundle
对象或者通过Gradle插件类型安全得传递数据。遵照以下步骤在destinations之间使用Bundle对象传递数据。如果你想使用Gradle,请遵照Pass data between destinations in a type-safe way
的介绍。
1、在Graph Editor,点击接受参数的destination。该destination会高亮。
2、在属性面板的参数部分点击 Add(+),会显示空名字和默认值字段。
3、在名字字段双击输入参数名字。
4、按压Tab,输入参数的默认值。
5、点击上述destination的action。参数的默认值应该包含你新增的参数。
6、点击Text去切换XML View。一个参数元素,包含名字和默认值属性,已经被添加到该destination。


  

当你使用safeargs plugin,会为action,destinations的接受者和发送者创建简单对象和构造类。这些类是:

  • 一个类为action源起的destination,后缀“Directions”。因此,如果起始的fragment叫做SpecifyAmountFragment,那么生成的类就叫做SpecifyAmountFragmentDirections。这个类有一个以传递参数的action来命名,去绑定参数,比如confirmationAction()。
  • 一个匿名内部类,名字基于传递参数的action。如果传递的action叫做confirmationAction,类就被命名为ConfirmationAciton。
  • 一个类用于接受destination,后缀Args,所以,如果destination fragment叫做ComfirmationFragment,生成的类就叫做ConfirmationFragmentArgs。使用这个类的fromBundle()方法获取参数。
    示例代码:
@Override
public void onClick(View view) {
  EditText amountTv = (EditText) getView().findViewById(R.id.editTextAmount);
  int amount = Integer.parseInt(amountTv.getText().toString());
  ConfirmationAction action =
          SpecifyAmountFragmentDirections.confirmationAction()
  action.setAmount(amount)
  Navigation.findNavController(view).navigate(action);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    TextView tv = view.findViewById(R.id.textViewAmount);
    int amount = ConfirmationFragmentArgs.fromBundle(getArguments()).getAmount();
    tv.setText(amount + "")
}

Group destinations into a nested navigation graph

在navigation graph内,可以把一些相关的destination是分组为sub-graph,如果包含sub-graph的是root-graph,那么这个sub-graph被称作“nestedgraph”,Nestedgraph在组织和重用App UI的模块上是很有用的,比如登录流程。
和root graph一样,nested graph必须也要有一个启动的destination作为唯一的标识。nested graph封装了它的destinations。nested graph外部,root graph之内的destination只能通过root graph的启动destination访问nested graph。图6 展示了一个simple money transfer app的navigation graph。这个graph有两个流程:转钱流程和余额流程。

【译】Android Jetpack 架构导航组件之Navigation_第5张图片
图6 navigation-pre-nestedgraph.png

把destinations分组为nested graph:
1、在graph editor,按住 shift点击需要加入nested graph的destination,该destination高亮。
2、打开菜单选择 Move to Nested Graph > New Graph,如图7.
【译】Android Jetpack 架构导航组件之Navigation_第6张图片
图7navigation-nestedgraph.png

3、点击高亮nested graph,属性面板显示如下:

  • Type字段显示“Nested Graph”。
  • Id字段是系统为nested graph指定的。Id用来在代码中引用这个nested graph。
    4、双击nested graph查看内部的destinations。
    5、在destinations列表,点击root返回root graph。
    6、点击Text进入XML视图。


   
       
       
   
   
   
       
           
       
       
   

7、在你的代码里,使用action id来关联root graph 和 nested graph。

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

Reference other navigation graphs using

在 navigation graph内,可以通过引用其它navigation graph,其等价于使用nested graph。以此使用其它module或者library中的navigation。


只有一个app:graph属性,且不允许其它任何属性。

Create a deep link for a destination

Add an intent filter for a deep link

Create a transition between destinations

AndroidX命名空间迁移
Verify Android App Links (Deep Links和Android App Links的区别)

你可能感兴趣的:(【译】Android Jetpack 架构导航组件之Navigation)