暖人先暖心 發表於 2020-2-22 11:07:00

Android开发 Navigation—NavController的使用详解

<h1><span style="color: rgba(0, 128, 128, 1)">版权声明</span></h1>
<p>本文来自博客园,作者:观心静&nbsp;,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/12344572.html</p>
<div>本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。</div>
<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1>
<p>  这篇博客只讲解NavController控制器的一些API的使用详解与应用环境的说明。不在讲解一些Navigation的基础知识,如果你还不了解Navigation建议你去另外一篇博客了解&nbsp;https://www.cnblogs.com/guanxinjing/p/11555217.html</p>
<h1><span style="color: rgba(0, 128, 128, 1)">为什么要了解NavController</span></h1>
<p>  NavController字面意思就是导航控制器,它负责操作Navigation框架下的Fragment的跳转与退出、动画、监听当前Fragment信息,当然这些是基本操作。但是更重要的是知道它可以使用的范围,一般情况下我们以为它只能在Fragment里调用,实际情况下它在Activity里也可以调用。灵活的使用它,可以帮你实现所有形式的页面跳转。除此之外你甚至还能使用<span style="color: rgba(0, 0, 0, 1)">TabLayout配合Navigation进行主页的分页设计。极端点你甚至还能在某个分页里再次添加<span style="color: rgba(0, 0, 0, 1)">TabLayout配合Navigation</span>进行嵌套设计。</span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">如何获取NavController实例</span></h1>
<p>在Activity中获取</p>
<div class="cnblogs_code">
<pre>NavController controller = Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>, R.id.fragment); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这个R.id.fragment就是Activity布局里fragment控件的id</span></pre>
</div>
<p>在Fragment中获取</p>
<div class="cnblogs_code">
<pre>NavControllernavController = Navigation.findNavController(getView());</pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">API讲解与使用场景</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">请注意一下代码有些是在Activity里操作NavController,但是实际上下面的代码也可以在Fragment里执行,这2者是没有区别的。所以这里并不重复贴Fragment里的代码了</span></p>
<h2><span style="color: rgba(0, 0, 0, 1)">在Activity根据业务需要使用setGraph切换不同的Navigation</span></h2>
<p><span style="color: rgba(0, 0, 0, 1)">xml</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">可以把&nbsp; &nbsp;</span>app:navGraph= 这个属性去除</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">fragment
      </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/fragment"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="match_parent"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="match_parent"</span><span style="color: rgba(255, 0, 0, 1)">
      android:name</span><span style="color: rgba(0, 0, 255, 1)">="androidx.navigation.fragment.NavHostFragment"</span><span style="color: rgba(255, 0, 0, 1)">
      app:defaultNavHost</span><span style="color: rgba(0, 0, 255, 1)">="true"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span></pre>
</div>
<p><span style="color: rgba(0, 0, 0, 1)">java</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(@Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
     setContentView(R.layout.activity_demo);  
      initNav(</span>2<span style="color: rgba(0, 0, 0, 1)">);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> initNav(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> type){
      NavController controller </span>= Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span>, R.id.fragment); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在Activity里获取NavController实例</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span> (type == 1<span style="color: rgba(0, 0, 0, 1)">){
            controller.setGraph(R.navigation.demo_one_nav);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置xml文件</span>
            <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      }
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (type == 2<span style="color: rgba(0, 0, 0, 1)">){
            Bundle bundle </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Bundle();
            bundle.putString(</span>"name", "demo"<span style="color: rgba(0, 0, 0, 1)">);
            controller.setGraph(R.navigation.demo_two_nav, bundle); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置xml文件的并传入数据,这个数据可以在启动的Fragment里获取到</span>
            <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      }
      DemoActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.finish();
    }</span></pre>
</div>
<p>上面的第二种方式,我们在设置xml文件的同时还传入了数据,这个数据可以在Fragment里建议用下面的方式获取</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onAttach(@NonNull Context context) { <span style="color: rgba(0, 128, 0, 1)">//在Fragment里重写onAttach,在这里获取可以保证数据不会为null</span>
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onAttach(context);
      Log.e(</span>"触发", "onAttach: 传入数据=" + getArguments().getString("name"<span style="color: rgba(0, 0, 0, 1)">));
    }</span></pre>
</div>
<h2>在Activity使用navigate跳转Fragment</h2>
<h3>使用Action的id跳转</h3>
<p><span style="color: rgba(255, 0, 0, 1)"><strong>请注意!</strong></span>下面的navigate的值是<span style="color: rgba(0, 0, 128, 1); font-weight: bold">action</span>的id,而使用action的id跳转Fragment是不能凭空在没有上一个Fragment的情况下跳转下一个Fragment的,这是会报错的。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(@Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
      setContentView(R.layout.activity_demo);
      NavController controller </span>= Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, R.id.fragment);
      controller.setGraph(R.navigation.demo_one_nav);
      controller.navigate(R.id.action_oneFragment_to_twoFragment); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从默认启动的oneFragment跳转到TwoFragment</span>
<span style="color: rgba(0, 0, 0, 1)">
    }</span></pre>
</div>
<h3><span style="color: rgba(0, 0, 0, 1)">使用fragment的id直接跳转</span></h3>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">fragment
      </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/threeFragment"</span><span style="color: rgba(255, 0, 0, 1)">
      android:name</span><span style="color: rgba(0, 0, 255, 1)">="com.zh.fragmentdemo.ThreeFragment"</span><span style="color: rgba(255, 0, 0, 1)">
      android:label</span><span style="color: rgba(0, 0, 255, 1)">="fragment_three"</span><span style="color: rgba(255, 0, 0, 1)">
      tools:layout</span><span style="color: rgba(0, 0, 255, 1)">="@layout/fragment_three"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span></pre>
</div>
<p>在activity里</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(@Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
      setContentView(R.layout.activity_demo);
      NavController controller </span>= Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, R.id.fragment);
      controller.setGraph(R.navigation.demo_one_nav);
      controller.navigate(R.id.threeFragment); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">直接跳转到threeFragment</span>
<span style="color: rgba(0, 0, 0, 1)">
    }</span></pre>
</div>
<p>使用在navigation xml文件的fragment的id可以直接跳转到某一个Fragment里,这种跳转方式可以不需要是否有上一个Fragment。例如我们需要直接跳转到threeFragment。<strong><span style="color: rgba(255, 0, 0, 1)">请注意!</span>下面使用navigate直接指定id目标Fragment上是会创建一个新的Fragment到堆栈里的。这个时候就会看到每次navigate都会创建一个新的实例从而导致内存泄漏</strong>.&nbsp;实际项目在一些tabLayout功能下最好配合popBackStack来使用。如果popBackStack跳转到指定目标为false,在使用navigate来跳转到指定Fragment。如下</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">if</span> (!mNavController.popBackStack(R.id.threeFragment, <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">)) {
  mNavController.navigate(R.id.threeFragment);
}</span></pre>
</div>
<p>&nbsp;</p>
<h2>使用navigate带动画跳转或者弹出Fragment</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(@Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
      setContentView(R.layout.activity_demo);
      NavController controller </span>= Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, R.id.fragment);
      controller.setGraph(R.navigation.demo_one_nav);
      NavOptions navOptions </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> NavOptions.Builder()
                .setEnterAnim(R.anim.from_right) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">进入动画</span>
                .setExitAnim(R.anim.to_left)    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">退出动画</span>
                .setPopEnterAnim(R.anim.to_left)    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">弹出进入动画</span>
                .setPopExitAnim(R.anim.from_right)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">弹出退出动画</span>
<span style="color: rgba(0, 0, 0, 1)">                .build();
      controller.navigate(R.id.action_oneFragment_to_twoFragment, </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)"> , navOptions);
    }</span></pre>
</div>
<p>&nbsp;</p>
<h2>使用popBackStack弹出Fragment</h2>
<p>方式一 弹出当前的Fragment</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(@Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
      setContentView(R.layout.activity_demo);
      NavController controller </span>= Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, R.id.fragment);
      controller.setGraph(R.navigation.demo_one_nav);
      controller.navigate(R.id.action_oneFragment_to_twoFragment); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从oneFragment进入到twoFragment</span>
      controller.navigate(R.id.action_twoFragment_to_threeFragment);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从twoFragment进入到threeFragment</span>
      controller.popBackStack(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">弹出threeFragment,回到twoFragment</span>
<span style="color: rgba(0, 0, 0, 1)">      
    }</span></pre>
</div>
<p>方式二 弹出到指定的Fragment,并且设置布尔值是否连这个指定Fragment一起弹出</p>
<p><span style="color: rgba(255, 0, 0, 1)"><strong>请注意! <span style="color: rgba(0, 0, 0, 1)">请重视 public boolean popBackStack(@IdRes int destinationId, boolean inclusive) 这个方法。因为此方法可以实现<span style="color: rgba(255, 0, 0, 1)">清空中间导航栈堆</span>的需求,举例假如 现在有 A -&gt; B -&gt; C -&gt; D 这四个导航Fragment,如果我们现在当前导航到D并且想回到A,如果使用navigate()方法回到A,你就会发现用A Fragment里按返回键,不是直接退出而是直接到D&nbsp; Fragment。 如果是使用popBackStack(@IdRes int destinationId, boolean inclusive)方法,就不会回到D Fragment</span></strong></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(@Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
      setContentView(R.layout.activity_demo);
      NavController controller </span>= Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, R.id.fragment);
      controller.setGraph(R.navigation.demo_one_nav);
      controller.navigate(R.id.action_oneFragment_to_twoFragment); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从oneFragment进入到twoFragment</span>
      controller.navigate(R.id.action_twoFragment_to_threeFragment); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">从twoFragment进入到threeFragment</span>
      controller.popBackStack(R.id.twoFragment, <span style="color: rgba(0, 0, 255, 1)">true</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">弹出到twoFragment,第二个参数的布尔值如果为true则表示参数一的Fragment一起弹出,这个时候我们就会回到oneFragment</span>
<span style="color: rgba(0, 0, 0, 1)">
    }</span></pre>
</div>
<p>另外,如果你发现目标Fragment不存在跳转失败后,你可以参考以下这种实现,直接创建指定目标的Fragment</p>
<div class="cnblogs_code">
<pre>                  <span style="color: rgba(0, 0, 255, 1)">boolean</span> jumpStatus = Navigation.findNavController(getView()).popBackStack(R.id.scenesTimingFragment, <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">jumpStatus){
                        Navigation.findNavController(getView()).navigate(R.id.scenesTimingFragment);
                  }</span></pre>
</div>
<h2>navigateUp() 向上导航</h2>
<div class="cnblogs_code">
<pre> Navigation.findNavController(getView()).navigateUp();</pre>
</div>
<p>navigateUp也是执行返回上一级Fragment的功能。 有小朋友会问了popBackStack和navigateUp()的区别是什么呢?</p>
<p>navigateUp向上返回的功能其实也是调用popBackStack的。 但是,navigateUp的源码里多了一层判断,源码如下:就是判断这个Navigation是否是最后一个Fragment,并且这个Navigation与里面的Fragment是不是有可能是其他Navigation跳转过来的。如果是其他Navigation跳转过来的就会回到之前的Navigation上。并且销毁当前Navigation的Activity。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> navigateUp() {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (getDestinationCountOnBackStack() == 1<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> If there's only one entry, then we've deep linked into a specific destination
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> on another task so we need to find the parent and start our task from there</span>
            NavDestination currentDestination =<span style="color: rgba(0, 0, 0, 1)"> getCurrentDestination();
            </span><span style="color: rgba(0, 0, 255, 1)">int</span> destId =<span style="color: rgba(0, 0, 0, 1)"> currentDestination.getId();
            NavGraph parent </span>=<span style="color: rgba(0, 0, 0, 1)"> currentDestination.getParent();
            </span><span style="color: rgba(0, 0, 255, 1)">while</span> (parent != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (parent.getStartDestination() !=<span style="color: rgba(0, 0, 0, 1)"> destId) {
                  TaskStackBuilder parentIntents </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> NavDeepLinkBuilder(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">)
                            .setDestination(parent.getId())
                            .createTaskStackBuilder();
                  parentIntents.startActivities();
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (mActivity != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                        mActivity.finish();
                  }
                  </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
                }
                destId </span>=<span style="color: rgba(0, 0, 0, 1)"> parent.getId();
                parent </span>=<span style="color: rgba(0, 0, 0, 1)"> parent.getParent();
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> We're already at the startDestination of the graph so there's no 'Up' to go to</span>
            <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
      } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> popBackStack();
      }
    }</span></pre>
</div>
<h2>使用getCurrentDestination获取当前导航目的地</h2>
<div class="cnblogs_code">
<pre>      NavController controller = Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, R.id.fragment);
      NavDestination navDestination </span>= controller.getCurrentDestination(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取当前目的地的信息</span>
      Log.e(TAG, "onCreate: NavigatorName = " +<span style="color: rgba(0, 0, 0, 1)"> navDestination.getNavigatorName());
      Log.e(TAG, </span>"onCreate: id = " +<span style="color: rgba(0, 0, 0, 1)"> navDestination.getId());
      Log.e(TAG, </span>"onCreate: Parent = " + navDestination.getParent());</pre>
</div>
<h2>&nbsp;添加或者移除导航目的地监听</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"> @Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(@Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
      setContentView(R.layout.activity_demo);
      NavController controller </span>= Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, R.id.fragment);
      NavController.OnDestinationChangedListener listener </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> NavController.OnDestinationChangedListener() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
                Log.e(TAG, </span>"onDestinationChanged: id = " +<span style="color: rgba(0, 0, 0, 1)"> destination.getId());
            }
      };
      controller.addOnDestinationChangedListener(listener); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加监听</span>
<span style="color: rgba(0, 0, 0, 1)">      controller.setGraph(R.navigation.demo_one_nav);
      controller.navigate(R.id.action_oneFragment_to_twoFragment);
      controller.navigate(R.id.action_twoFragment_to_threeFragment);
      controller.removeOnDestinationChangedListener(listener); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">移除监听</span>
    }</pre>
</div>
<h2>getNavInflater&nbsp; Navigation创建</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"> @Override
    </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onCreate(@Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
      setContentView(R.layout.activity_demo);
      NavController controller </span>= Navigation.findNavController(DemoActivity.<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">, R.id.fragment);
      NavGraph navGraph </span>= controller.getNavInflater().inflate(R.navigation.demo_one_nav); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获得NavGraph 就是navigation,可以操作各种Fragment的增加或移除功能,一个是代码操作一个是xml操作</span>
      controller.setGraph(navGraph); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">其实用这种方式setGraph(navGraph)与直接setGraph(R.navigation.demo_one_nav);一样</span>
    }</pre>
</div>
<h2>Fragment里嵌套Navigation</h2>
<p>在Fragment里</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onViewCreated(view, savedInstanceState);
      mTabLayout </span>=<span style="color: rgba(0, 0, 0, 1)"> (TabLayout) view.findViewById(R.id.tab_layout);
      mAddBtn </span>=<span style="color: rgba(0, 0, 0, 1)"> (ImageView) view.findViewById(R.id.add_btn);
      mNavController </span>= Navigation.findNavController(getActivity(), R.id.scenes_fragment);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">请注意,这个 R.id.scenes_fragment是Fragment布局里的fragment</span>
<span style="color: rgba(0, 0, 0, 1)">
    }</span></pre>
</div>
<h1>判断当前页面显示的Fragment是不是目标Fragment</h1>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">public</span> fun &lt;F : Fragment&gt; isActiveFragment(fragmentClass: Class&lt;F&gt;<span style="color: rgba(0, 0, 0, 1)">): Boolean {
      val navHostFragment </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.supportFragmentManager.fragments.first() as NavHostFragment
      navHostFragment.childFragmentManager.fragments.forEach {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (fragmentClass.isAssignableFrom(it.javaClass)) {
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">
            }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
    }</span></pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>End</p>

</div>
<div id="MySignature" role="contentinfo">
    <div style="text-align: center">
    <p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/12344572.html </p>
    <div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/12344572.html
頁: [1]
查看完整版本: Android开发 Navigation—NavController的使用详解