人丑嘴不甜长得危险还没钱 發表於 2019-9-20 10:14:00

Android开发 navigation入门详解

<h1><span style="color: rgba(0, 128, 128, 1)">版权声明</span></h1>
<p>本文来自博客园,作者:观心静&nbsp;,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/11555217.html</p>
<div>本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。</div>
<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1>
<p>  Google 在2018年推出了 Android Jetpack,在Jetpack里有一种管理fragment的新架构模式,那就是navigation. 字面意思是导航,但是除了做APP引导页面以外.也可以使用在App主页分tab的情况.. 甚至可以一个功能模块就一个activity大部分页面UI都使用fragment来实现,而navigation就成了管理fragment至关重要的架构.</p>
<p>  但是,它不单单只能管理fragment也可以管理activity.这点你格外注意.</p>
<h1><span style="color: rgba(0, 128, 128, 1)">使用条件</span></h1>
<p>  你的Android studio 必需升级到3.2版本以上,此博客正在写的时候Android studio已经到达3.5,所以升级到最新版本即可.</p>
<h1><span style="color: rgba(0, 128, 128, 1)">依赖</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 0, 0, 1)">最新版本可以通过</span> https://developer.android.google.cn/jetpack/androidx/releases/navigation?hl=zh_cn <span style="color: rgba(0, 0, 0, 1)">查看&nbsp;</span></span></span></p>
<pre class="clear-for-copy highlighter-hljs" data-dark-theme="true"><code>dependencies {
&nbsp; val nav_version = "2.5.3"

&nbsp; // Java language implementation
&nbsp; implementation("androidx.navigation:navigation-fragment:$nav_version")
&nbsp; implementation("androidx.navigation:navigation-ui:$nav_version")

&nbsp; // Kotlin
&nbsp; implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
&nbsp; implementation("androidx.navigation:navigation-ui-ktx:$nav_version")

&nbsp; // Feature module Support
&nbsp; implementation("androidx.navigation:navigation-dynamic-features-fragment:$nav_version")

&nbsp; // Testing Navigation
&nbsp; androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")

&nbsp; // Jetpack Compose Integration
&nbsp; implementation("androidx.navigation:navigation-compose:$nav_version")
}</code></pre>
<p><span style="color: rgba(0, 0, 0, 1)">另外还需要在根目录gradle.properties 文件中添加</span></p>
<div class="cnblogs_code">
<pre>android.enableJetifier=<span style="color: rgba(0, 0, 255, 1)">true</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">基本使用流程</span></h1>
<h2><span style="color: rgba(35, 111, 161, 1)">创建navigation目录</span></h2>
<p>1.选中项目资源文件夹 res 右击 &gt;&gt; New &gt;&gt; New Resource Directory</p>
<p>2.选中navigation 点击创建 (注意这个目录只有在Android studio3.2版本以上才能出现)</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201909/1497956-20190920101312349-2097413820.png" alt=""></p>
<h2><span style="color: rgba(35, 111, 161, 1)">创建navigation目录下的xml文件</span></h2>
<p>1.选中项目资源文件夹 res 右击 &gt;&gt; New &gt;&gt; New Resource File</p>
<p>2.选择navigation ,输入xml文件名称,点击ok创建</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201909/1497956-20190920101657907-1042388041.png" alt=""></p>
<h2><span style="color: rgba(35, 111, 161, 1)">配置创建的xml文件</span></h2>
<p>&nbsp;上面我们创建了一个叫demo_nav.xml的navigation文件,现在我们需要来设配它来管理fragment</p>
<p>&nbsp;1.打开这个文件选择<img src="https://img2018.cnblogs.com/blog/1497956/201909/1497956-20190920102031528-1381602829.png" alt="">,模式使用视图手动配置.</p>
<p>2.切换到Design模式后,我们可以看到下面这个界面(恩,一片空白). 我们可以在左上角点击<img src="https://img2018.cnblogs.com/blog/1497956/201909/1497956-20190920102430017-1380725255.png" alt="">添加图标,进入添加内容的操作.</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201909/1497956-20190920102349263-653219683.png" alt=""></p>
<p>3.点击<img src="https://img2018.cnblogs.com/blog/1497956/201909/1497956-20190920102430017-1380725255.png" alt="">后,可以看到下面这个弹窗,这里解释一下:</p>
<p>第一个 Create new destinattion,字面意思创建一个新目标(其实就是创建fragment,当然你也可以手动另外创建fragment不一定需要在这里创建)</p>
<p>第二个 placeholder,这个就是重点了. 这是一个管理fragment跳转的节点,我们点击后可以创建它.为了了解它的使用方式,点击3次创建三个节点</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201909/1497956-20190920102552079-1565083163.png" alt=""></p>
<p>4.节点创建后可以看到三个节点(看下面图片,这些节点都是我已经导入fragment了.不要急后面会讲解如何导入).<strong>这里有一个重点! 你可以点击这些页面(会有一个蓝点),点击蓝点按住向右分配它需要跳转的另外一个页面.(它会自动生成一些我们跳转的代码)</strong></p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201909/1497956-20190920110409075-418275180.png" alt=""></p>
<p>6.然后点击左下角的Text模式,在Text模式下,可以看到如下代码,在上面的图片中你可以很清楚的看到创建了3个节点,并且是一个跳转一个的.从第一个fragment跳转到第二个fragment,再从第二个fragment跳转到第三个fragment</p>
<p>下面我们来重点讲解下下面的这些代码的关键点了:</p>
<h3>在<span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(128, 0, 0, 1)">navigation</span></span>里的属性:</h3>
<p>1.<span style="color: rgba(255, 0, 0, 1)">android:id<span style="color: rgba(0, 0, 255, 1)">="@+id/demo_nav" <span style="background-color: rgba(255, 255, 255, 1); color: rgba(0, 0, 0, 1)">这个属性是你这个xml文件navigation的id,<strong>很重要</strong>,我们需要在activity的xml布局里引用,记得写上不要忘记</span><br></span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">2</span>.<span style="color: rgba(255, 0, 0, 1)">app:startDestination<span style="color: rgba(0, 0, 255, 1)">="@id/one" <span style="color: rgba(0, 0, 0, 1)">这个属性是你首次加载的第一个页面,<strong>很重要</strong>,一般就是第一个fragment</span></span></span></span></span></p>
<h3><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">在<span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(128, 0, 0, 1)">fragment</span></span> 里的属性:</span></span></span></span></span></h3>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">其实就是一个节点你也可以理解成一个fragment</span></span></span></span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">1.<span style="color: rgba(255, 0, 0, 1)">android:id<span style="color: rgba(0, 0, 255, 1)">="@+id/one"</span></span>&nbsp; 每一个fragment节点都需要有自己的id,<span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><strong>很重要</strong></span></span></span></span></span>. 我们需要在后面的节点上使用这些id指定跳转目标</span></span></span></span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">2.<span style="color: rgba(255, 0, 0, 1)">android:name<span style="color: rgba(0, 0, 255, 1)">="demo.yt.com.demo.fragment.BlankFragment"&nbsp;&nbsp; <span style="color: rgba(0, 0, 0, 1)">这个属性是你这个节点所对应的fragment(需要你导入指定的fragment文件路径),<strong>这个很重要</strong></span></span></span></span></span></span></span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">3.<span style="color: rgba(255, 0, 0, 1)">android:label<span style="color: rgba(0, 0, 255, 1)">="BlankFragment"</span></span> 一个标签名称,用于记录这个节点的标签信息(大概可能是在代码里的Intent里获取来知晓此次是那个fragment节点在跳转,没深究了)</span></span></span></span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">4.<span style="color: rgba(255, 0, 0, 1)">tools:layout<span style="color: rgba(0, 0, 255, 1)">="@layout/fragment_blank"</span></span> 这个属性不是重要的,设置它后你可以在切换到Design模式后看到,视图页面的fragment的预览图(就在上面的图片里,可以直接看到<span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">fragment</span></span></span></span></span>效果)</span></span></span></span></span></p>
<h3><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">在<span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(128, 0, 0, 1)">action</span></span> 里的属性:</span></span></span></span></span></h3>
<p><span style="color: rgba(0, 0, 0, 1)">action</span> 负责编写跳转动作</p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">1. <span style="color: rgba(255, 0, 0, 1)">android:id<span style="color: rgba(0, 0, 255, 1)">="@+id/action_one_to_two" <span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><strong>这个很重要</strong></span></span></span></span></span></span></span></span><span style="color: rgba(0, 0, 0, 1)">,</span></span></span></span><span style="color: rgba(0, 0, 0, 1)">它是这个跳转动作的id, 这个id我们将在后面的代码中调用,用于执行fragment的跳转</span></span></span></span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">2. </span><span style="color: rgba(255, 0, 0, 1)">app:destination<span style="color: rgba(0, 0, 255, 1)">="@id/two" <span style="color: rgba(0, 0, 0, 1)">跳转的目标</span><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)">fragment</span></span></span></span></span></span></span></span></span></span></span></span>,<span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><strong>这个很重要</strong></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;?</span><span style="color: rgba(255, 0, 255, 1)">xml version="1.0" encoding="utf-8"</span><span style="color: rgba(0, 0, 255, 1)">?&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">navigation </span><span style="color: rgba(255, 0, 0, 1)">xmlns:android</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res/android"</span><span style="color: rgba(255, 0, 0, 1)">
    xmlns:app</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res-auto"</span><span style="color: rgba(255, 0, 0, 1)">
    xmlns:tools</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/tools"</span><span style="color: rgba(255, 0, 0, 1)">
    android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/demo_nav"</span><span style="color: rgba(255, 0, 0, 1)">
    app:startDestination</span><span style="color: rgba(0, 0, 255, 1)">="@id/one"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>


    <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/one"</span><span style="color: rgba(255, 0, 0, 1)">
      android:name</span><span style="color: rgba(0, 0, 255, 1)">="demo.yt.com.demo.fragment.BlankFragment"</span><span style="color: rgba(255, 0, 0, 1)">
      android:label</span><span style="color: rgba(0, 0, 255, 1)">="BlankFragment"</span><span style="color: rgba(255, 0, 0, 1)">
      tools:layout</span><span style="color: rgba(0, 0, 255, 1)">="@layout/fragment_blank"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">action
            </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/action_one_to_two"</span><span style="color: rgba(255, 0, 0, 1)">
            app:destination</span><span style="color: rgba(0, 0, 255, 1)">="@id/two"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">fragment</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

    <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/two"</span><span style="color: rgba(255, 0, 0, 1)">
      android:name</span><span style="color: rgba(0, 0, 255, 1)">="demo.yt.com.demo.fragment.Blank2Fragment"</span><span style="color: rgba(255, 0, 0, 1)">
      android:label</span><span style="color: rgba(0, 0, 255, 1)">="BlankFragment"</span><span style="color: rgba(255, 0, 0, 1)">
      tools:layout</span><span style="color: rgba(0, 0, 255, 1)">="@layout/fragment_blank2"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">action
            </span><span style="color: rgba(255, 0, 0, 1)">android:id</span><span style="color: rgba(0, 0, 255, 1)">="@+id/action_two_to_three"</span><span style="color: rgba(255, 0, 0, 1)">
            app:destination</span><span style="color: rgba(0, 0, 255, 1)">="@id/three"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">fragment</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

    <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/three"</span><span style="color: rgba(255, 0, 0, 1)">
      android:name</span><span style="color: rgba(0, 0, 255, 1)">="demo.yt.com.demo.fragment.Blank3Fragment"</span><span style="color: rgba(255, 0, 0, 1)">
      android:label</span><span style="color: rgba(0, 0, 255, 1)">="BlankFragment"</span><span style="color: rgba(255, 0, 0, 1)">
      tools:layout</span><span style="color: rgba(0, 0, 255, 1)">="@layout/fragment_blank3"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">navigation</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<h2><span style="color: rgba(35, 111, 161, 1)">让navigation与Activity关联起来</span></h2>
<p>&nbsp;  现在我们已经创建了navigation,但是使用它还需要一个根Activity,它毕竟还是需要依托Activity的.</p>
<p>&nbsp;1.创建了一个叫DemoActivity的Activity.这个没啥,下面来看这个Activity的布局xml怎么配(如下xml代码)</p>
<p><strong>我们就关注<span style="color: rgba(0, 0, 0, 1)">fragment的一些属性</span></strong></p>
<p>1.<span style="color: rgba(255, 0, 0, 1)">android:name<span style="color: rgba(0, 0, 255, 1)">="androidx.navigation.fragment.NavHostFragment"</span></span>&nbsp; <span style="color: rgba(255, 0, 0, 1)"><strong>这个非常重要</strong></span>,这是你告知<span style="color: rgba(0, 0, 0, 1)">fragment</span>需要使用navigation模式的关键属性,另外<strong>它是固定死的.你必需写.</strong></p>
<p>2. <span style="color: rgba(255, 0, 0, 1)">app:defaultNavHost<span style="color: rgba(0, 0, 255, 1)">="true"</span></span>&nbsp; 这是你实现物理按键(比如返回键),是按一下退出一个<span style="color: rgba(0, 0, 0, 1)">fragment</span> 还是直接退出这个Activity的关键属性</p>
<p>3.<span style="color: rgba(255, 0, 0, 1)">app:navGraph<span style="color: rgba(0, 0, 255, 1)">="@navigation/demo_nav"</span></span>&nbsp; <span style="color: rgba(0, 0, 0, 1)"><strong>很重要</strong>,这就是我们前面创建的navigation的xml文件</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;?</span><span style="color: rgba(255, 0, 255, 1)">xml version="1.0" encoding="utf-8"</span><span style="color: rgba(0, 0, 255, 1)">?&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">androidx.constraintlayout.widget.ConstraintLayout
    </span><span style="color: rgba(255, 0, 0, 1)">xmlns:android</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res/android"</span><span style="color: rgba(255, 0, 0, 1)">
    xmlns:app</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res-auto"</span><span style="color: rgba(255, 0, 0, 1)">
    xmlns:tools</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/tools"</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)">
    tools:context</span><span style="color: rgba(0, 0, 255, 1)">=".fragment.DemoActivity"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

    <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/demo_fragment"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_width</span><span style="color: rgba(0, 0, 255, 1)">="0dp"</span><span style="color: rgba(255, 0, 0, 1)">
      android:layout_height</span><span style="color: rgba(0, 0, 255, 1)">="0dp"</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(255, 0, 0, 1)">
      app:navGraph</span><span style="color: rgba(0, 0, 255, 1)">="@navigation/demo_nav"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintTop_toTopOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintBottom_toBottomOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintLeft_toLeftOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(255, 0, 0, 1)">
      app:layout_constraintRight_toRightOf</span><span style="color: rgba(0, 0, 255, 1)">="parent"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>

<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">androidx.constraintlayout.widget.ConstraintLayout</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<h1><span style="color: rgba(22, 145, 121, 1)">navigate跳转与popBackStack返回</span></h1>
<p>&nbsp;进入到DemoActivity后,首先会自动加载到第一个<span style="color: rgba(0, 0, 0, 1)">fragment</span>. 然后我们看看如何跳转到其他<span style="color: rgba(0, 0, 0, 1)">fragment</span>中</p>
<p>&nbsp;1.从第一个碎片跳转到第二个碎片,关键代码&nbsp; <span style="color: rgba(0, 0, 0, 1)">Navigation.findNavController(getView()).navigate(R.id.action_one_to_two);</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> BlankFragment <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Fragment {
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Button mBtnInputFragment2;

    @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)"> onCreate(Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">final</span> View view = inflater.inflate(R.layout.fragment_blank, container, <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);;
      mBtnInputFragment2 </span>=<span style="color: rgba(0, 0, 0, 1)"> view.findViewById(R.id.btn_input_fragment2);
      mBtnInputFragment2.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @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)"> onClick(View v) {
                Navigation.findNavController(getView()).navigate(R.id.action_one_to_two);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这个id就是navigation里的action的id</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)"> view;
    }

    @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)"> onDestroy() {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onDestroy();
    }

    @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)"> onDetach() {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onDetach();
    }

}</span></pre>
</div>
<p>2.从第二个碎片返回到第一个碎片,关键代码 Navigation.<span style="font-style: italic">findNavController(getView()).popBackStack();</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> Blank2Fragment <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Fragment {
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Button mBtnInputFragment3, mBtnBack;

    @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)"> onCreate(Bundle savedInstanceState) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate(savedInstanceState);
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
      View view </span>= inflater.inflate(R.layout.fragment_blank2, container, <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
      mBtnInputFragment3 </span>=<span style="color: rgba(0, 0, 0, 1)"> view.findViewById(R.id.btn_input_fragment3);
      mBtnBack </span>=<span style="color: rgba(0, 0, 0, 1)"> view.findViewById(R.id.back);
      mBtnInputFragment3.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @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)"> onClick(View v) {
                Navigation.findNavController(getView()).navigate(R.id.action_two_to_three); </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)">            }
      });

      mBtnBack.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @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)"> onClick(View v) {
                Navigation.findNavController(getView()).popBackStack(); </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)">            }
      });
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> view;
    }

}</span></pre>
</div>
<h1><span style="color: rgba(22, 145, 121, 1)">popUpTo返回到指定位置</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">有时候在跳转了多个fragment目标后需要返回指定位置,例如A -&gt; B -&gt; C&nbsp; &nbsp;,现在我们要返回A这个fragment,<strong>就可以使用app:popUpTo这个属性,返回到指定位置并且会将B这个中间栈清理</strong>。但是实际开发上这种返回的方式,可能就是在navigation上表现很直观。并没有用NavController来返回指定位置来的方便。所以,我建议你还需要了解我另一篇博客 <span role="heading" aria-level="2">Android开发 Navigation—NavController的使用详解</span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)">代码如下:</span></p>
<pre class="language-xml highlighter-hljs" data-dark-theme="true"><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;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"
    android:id="@+id/demo_nav"
    app:startDestination="@id/AFragment"&gt;

    &lt;fragment
      android:id="@+id/AFragment"
      android:name="com.xx.ui.workrest.fragment.AFragment"
      android:label="AFragment"
      tools:layout="@layout/main_fragment_a" &gt;
      &lt;action
            android:id="@+id/action_AFragment_to_BFragment"
            app:destination="@id/BFragment" /&gt;
    &lt;/fragment&gt;
    &lt;fragment
      android:id="@+id/BFragment"
      android:name="com.xx.ui.workrest.fragment.BFragment"
      android:label="BFragment"
      tools:layout="@layout/main_fragment_b"&gt;
      &lt;action
            android:id="@+id/action_BFragment_to_CFragment"
            app:destination="@id/CFragment" /&gt;
    &lt;/fragment&gt;
    &lt;fragment
      android:id="@+id/CFragment"
      android:name="com.xx.ui.workrest.fragment.CFragment"
      android:label="CFragment"
      tools:layout="@layout/main_fragment_c" &gt;
      &lt;!--    注意这里的返回是使用的popUpTo      --&gt;
      &lt;action
            android:id="@+id/action_CFragment_to_AFragment"
            app:popUpTo="@id/AFragment" /&gt;
    &lt;/fragment&gt;
&lt;/navigation&gt;</code></pre>
<p><span style="color: rgba(0, 0, 0, 1)">在代码中调用,从C返回到A</span></p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>Navigation.findNavController(it).navigate(R.id.action_CFragment_to_AFragment)</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">popUpToInclusive&nbsp;</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">popUpToInclusive是用处是配合popUpTo使用的,在下面的代码里,A -&gt; B -&gt; C 进行导航,但是我们在B的action里设置了popUpTo与popUpToInclusive,这个时候B导航C的同时会将B清理出栈。 栈里只会剩下 A -&gt; C 的上下关系。</span></p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;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"
    android:id="@+id/demo_nav"
    app:startDestination="@id/AFragment"&gt;

    &lt;fragment
      android:id="@+id/AFragment"
      android:name="com.xx.ui.workrest.fragment.AFragment"
      android:label="AFragment"
      tools:layout="@layout/main_fragment_a" &gt;
      &lt;action
            android:id="@+id/action_AFragment_to_BFragment"
            app:destination="@id/BFragment" /&gt;
    &lt;/fragment&gt;
    &lt;fragment
      android:id="@+id/BFragment"
      android:name="com.xx.ui.workrest.fragment.BFragment"
      android:label="BFragment"
      tools:layout="@layout/main_fragment_b"&gt;
      &lt;!--      请注意这里的popUpTo与popUpToInclusive    --&gt;
      &lt;action
            android:id="@+id/action_BFragment_to_CFragment"
            app:destination="@id/CFragment"
            app:popUpTo="@id/BFragment"
            app:popUpToInclusive="true"/&gt;
    &lt;/fragment&gt;
    &lt;fragment
      android:id="@+id/CFragment"
      android:name="com.xx.ui.workrest.fragment.CFragment"
      android:label="CFragment"
      tools:layout="@layout/main_fragment_c" &gt;
    &lt;/fragment&gt;
&lt;/navigation&gt;</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">launchSingleTop 栈顶复用模式</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">当栈中已经包含了要跳转的指定页面,如果我们想在跳转到这个它将不会会再次创建这个页面,而是复用这个页面。这属性一般在TabBar与navigation配合使用的时候很有用。</span></p>
<pre class="language-xml highlighter-hljs" data-dark-theme="true"><code>    &lt;fragment
      android:id="@+id/AFragment"
      android:name="com.xx.ui.workrest.fragment.AFragment"
      android:label="AFragment"
      tools:layout="@layout/main_fragment_a" &gt;
      &lt;action
            android:id="@+id/action_AFragment_to_BFragment"
            app:launchSingleTop="@id/BFragment" /&gt;
    &lt;/fragment&gt;</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">跳转动画</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">一共有四种动画如下:</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">app:enterAnim 进入动画</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">app:exitAnim&nbsp; 退出动画</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">app:popEnterAnim&nbsp; 弹进动画(可能是给Dialog的)</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">app:popExitAnim 弹出动画</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">代码</span></p>
<pre class="language-xml highlighter-hljs" data-dark-theme="true"><code>    &lt;fragment
      android:id="@+id/AFragment"
      android:name="com.xx.ui.workrest.fragment.AFragment"
      android:label="AFragment"
      tools:layout="@layout/main_fragment_a" &gt;
      &lt;action
            android:id="@+id/action_AFragment_to_BFragment"
            app:destination="@id/BFragment"
            app:enterAnim="@anim/main_show_anim"
            app:exitAnim="@anim/main_hide_anim"
            app:popEnterAnim="@anim/main_hide_anim"
            app:popExitAnim="@anim/main_hide_anim" /&gt;
    &lt;/fragment&gt;</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">在navigation中加入Activity</span></h1>
<p>直接在navigation里添加activity即可</p>
<pre class="language-xml highlighter-hljs" data-dark-theme="true"><code>&lt;fragment
    android:id="@+id/editRemindFragment"
    android:name="com.xx.ui.workrest.fragment.EditRemindFragment"
    android:label="main_fragment_edit_remind"
    tools:layout="@layout/main_fragment_edit_remind" &gt;
    &lt;action
      android:id="@+id/action_editRemindFragment_to_demoActivity"
      app:destination="@id/demoActivity" /&gt;
&lt;/fragment&gt;
&lt;!--注意这里使用的是activity--&gt;
&lt;activity
    android:id="@+id/demoActivity"
    android:name="com.xx.ui.workrest.DemoActivity"
    android:label="DemoActivity"
    tools:layout="@layout/activity_demo"&gt;
&lt;/activity&gt;</code></pre>
<p><span style="color: rgba(0, 0, 0, 1)">跳转方式,还是一样的</span></p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>Navigation.findNavController(it).navigate(R.id.action_editRemindFragment_to_demoActivity)</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">在navigation中加入Dialog</span></h1>
<p>请注意这里的dialog是DialogFragment,下面代码中创建了DialogFragment的例子。如果你不太了解DialogFragment,请参考博客: <span role="heading" aria-level="2">Android开发 DialogFragment对话框详解</span></p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import com.lwlx.ui.main.databinding.MainDialogSelectBinding

class MyDialogFragment: DialogFragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
      val binding = MainDialogSelectBinding.inflate(inflater)
      return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)
    }
}</code></pre>
<p>在navigation中添加这个DialogFragment,请注意标识是使用的dialog</p>
<pre class="language-xml highlighter-hljs" data-dark-theme="true"><code>&lt;fragment
    android:id="@+id/remindListFragment"
    android:name="com.xx.ui.workrest.fragment.RemindListFragment"
    android:label="RemindListFragment"
    tools:layout="@layout/main_fragment_remind_list"&gt;
    &lt;action
      android:id="@+id/action_remindListFragment_to_myDialogFragment"
      app:destination="@id/myDialogFragment" /&gt;
&lt;/fragment&gt;
&lt;!--注意这里是使用的dialog--&gt;
&lt;dialog
    android:id="@+id/myDialogFragment"
    android:name="com.xx.ui.workrest.fragment.MyDialogFragment"
    android:label="MyDialogFragment"
    tools:layout="@layout/main_dialog_select"&gt;
&lt;/dialog&gt;</code></pre>
<p>然后,在代码里可以正常跳转</p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>Navigation.findNavController(it).navigate(R.id.action_remindListFragment_to_myDialogFragment)</code></pre>
<h1><span style="color: rgba(22, 145, 121, 1)">NavDeepLinkBuilder&nbsp; 深链接导航-配合状态栏通知使用</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">NavDeepLinkBuilder是配合通知使用的。在通知被点击后执行跳转功能的场景下,但是我们的跳转目标可能是某个nav下的fragment。 这个时候就需要使用NavDeepLinkBuilder,帮助我们跳转到某个nav下的指定fragment下。它的返回值pendingIntent也是配合通知使用的。代码如下:</span></p>
<pre class="lang-kotlin devsite-code-highlight highlighter-hljs" dir="ltr" translate="no" data-dark-theme="true"><code>val pendingIntent = NavDeepLinkBuilder(context)
&nbsp; &nbsp; .setGraph(R.navigation.nav_graph)
&nbsp; &nbsp; .setDestination(R.id.android)
&nbsp; &nbsp; .setArguments(args)
&nbsp; &nbsp; .setComponentName(DestinationActivity::class.java)
&nbsp; &nbsp; .createPendingIntent()</code></pre>
<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/11555217.html </p>
    <div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/11555217.html
頁: [1]
查看完整版本: Android开发 navigation入门详解