初嘗Android Jetpack 之Navigation


什么是 Navigation

  • The Navigation Architecture Component simplifies the implementation of navigation in an Android app

Navigation能做什么

利用Navigation組件對 Fragment 的原生支持,您可以獲得架構(gòu)組件的所有好處(例如生命周期和 ViewModel),同時讓此組件為您處理 FragmentTransaction 的復(fù)雜性。此外,Navigation組件還可以讓您聲明我們?yōu)槟幚淼霓D(zhuǎn)場。它可以自動構(gòu)建正確的“向上”和“返回”行為,包含對深層鏈接的完整支持,并提供了幫助程序,用于將導(dǎo)航關(guān)聯(lián)到合適的 UI 小部件,例如抽屜式導(dǎo)航欄和底部導(dǎo)航。

怎么使用Navigation

1.目前僅在Android Studio 3.2(目前是preview)版本以上才支持

2.添加項目依賴

新建一個項目,
(1)在project的build.gradle中,添加項目的依賴

buildscript {
    ...
    repositories {
            google()
    }
    dependencies {
            ...
            classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01'
    }
  }

(2)在app的build.gradle中添加如下依賴

apply plugin: 'androidx.navigation.safeargs'
dependencies {
    ...
    def nav_version = "1.0.0-alpha01"

    implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
    implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin 
    // optional - Test helpers
    androidTestImplementation "android.arch.navigation:navigation-testing:$nav_version" // use -ktx for Kotlin
}

(3)創(chuàng)建Navigation

  • 在新建的項目中,找到res文件夾,選中點擊右鍵選擇 New > Android resource file. 如下圖:


    1.png
  • 在彈出的對話框中,
    File name 一欄,填寫例如"nav_main",Resource type一欄選擇 Navigation,然后點擊OK,如下圖:


    2.png
  • 選擇創(chuàng)建好之后,會發(fā)現(xiàn)在res文件夾目錄下面,會自動生成一個navigation文件夾,然后剛才我們創(chuàng)建的xml文件nav_main也放在里面,如下圖:


    image.png
  • 點擊選中nav_main.xml雙擊打開,默認是Design模式,點擊
    image.png

    ,在彈出的對話框選擇 Create blank destination
    如下圖:


    image.png
  • 命名Fragment名稱為FragmentA,如下圖:


    image.png
  • 同上,再創(chuàng)建一個FragmentB
  • 在design模式下,創(chuàng)建導(dǎo)航鏈接,鼠標點擊FragmentA右邊中間圓圈不放拖動到FragmentB上釋放鼠標即可,如下圖:


    image.png
  • 點擊切換到Text模式,對應(yīng)nav_main.xml對應(yīng)生成的代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@id/fragmentA">

    <fragment
        android:id="@+id/fragmentA"
        android:name="navigation.xxw.com.navigationdemo.FragmentA"
        android:label="fragment_a"
        tools:layout="@layout/fragment_a" >
        <action
            android:id="@+id/action_fragmentA_to_fragmentB"
            app:destination="@id/fragmentB" />
    </fragment>
    <fragment
        android:id="@+id/fragmentB"
        android:name="navigation.xxw.com.navigationdemo.FragmentB"
        android:label="fragment_b"
        tools:layout="@layout/fragment_b" />
</navigation>
  • 其中fragmentA中的action是一個節(jié)點,destination就是要導(dǎo)航到fragmentB
  • MainActivity里面對應(yīng)不需要任何操作,設(shè)置好布局即可
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}
  • 接下來,在activity_main里面創(chuàng)建一個fragment,
    <fragment
        android:id="@+id/my_nav_host_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
  • 往里添加name屬性,指定在布局中要實例化NavHostFragment
android:name="androidx.navigation.fragment.NavHostFragment"
  • 添加navGraph屬性,是將NavHostFragment與我們剛才創(chuàng)建的navigation進行關(guān)聯(lián)
app:navGraph="@navigation/nav_main"
  • 添加defaultNavHost屬性,app:defaultNavHost="true",意思是NavHostFragment來攔截系統(tǒng)返回按鈕
app:defaultNavHost="true"
  • 而如果我們不設(shè)置defaultNavHost屬性,可以通過Navigation中的API對應(yīng)navigateUp方法來實現(xiàn)返回
Navigation.findNavController(it).navigateUp()
  • 最終我們定義的fragment就算定義好了,如下:
   <fragment
        android:id="@+id/my_nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_main" />
     <Button
        android:id="@+id/btn_go_to"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="點擊跳轉(zhuǎn)到Fragment B"
        app:layout_constraintTop_toBottomOf="@id/text" />
  • 在FragmentA中添加Button點擊跳轉(zhuǎn)事件,跳到FragmentB
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        view?.findViewById<Button>(R.id.btn_go_to)?.setOnClickListener {
            Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB)
        }
    }
  • 這里的id=action_fragmentA_to_fragmentB,就是上面設(shè)置的導(dǎo)航action的id
  • 最后運行跑一下
  • 傳遞參數(shù),第一種方式,通過bundle方式
        var bundle = Bundle()
        bundle.putString("name","zhangsan")
        view?.findViewById<Button>(R.id.btn_go_to_bundle)?.setOnClickListener {
            Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB,bundle)
        }
  • 在Fragment B頁面通過arguments 來獲取傳過來的bundle,
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        var bundle = arguments
        if (bundle != null) {
            var name = bundle?.getString("name")
            view.findViewById<TextView>(R.id.textB).text = "來自Fragment A頁面的參數(shù):"+name
        }
    }
  • 傳遞參數(shù),第二種方式,通過設(shè)置argument標簽,在需要接收參數(shù)的FragmentB頁面中設(shè)置argument標簽
    <fragment
        android:id="@+id/fragmentB"
        android:name="navigation.xxw.com.navigationdemo.FragmentB"
        android:label="fragment_b"
        tools:layout="@layout/fragment_b" >
        <argument android:name="text" android:defaultValue="Hello" app:type="string"/>
    </fragment>

其中name類似于map中的key,defaultValue是默認值,type對應(yīng)是數(shù)據(jù)類型
在Fragment A頁面?zhèn)髦低ㄟ^自動生成的FragmentBArgs來進行實現(xiàn)bundle

  val bundle1 = FragmentBArgs.Builder().setText("我是通過argument標簽實現(xiàn)傳值").build().toBundle()
  view?.findViewById<Button>(R.id.btn_go_to_argument)?.setOnClickListener {
     Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB,bundle1)
 }

同樣在FragmentB頁面中通過FragmentBArgs來獲取參數(shù)

//通過arguments獲取參數(shù)
        val text = FragmentBArgs.fromBundle(arguments).text
        view.findViewById<TextView>(R.id.textB).text = "arguments方式獲取參數(shù):"+text
  • PS:如果沒有在調(diào)用沒有自動生成FragmentBArgs方法,查看在app的build.gradle中添加如下依賴
apply plugin: 'androidx.navigation.safeargs'
  • 添加fragment之間跳轉(zhuǎn)動畫,可以通過action直接添加,在res文件夾創(chuàng)建anim文件夾,放入四個動畫slide_in_right.xml、slide_out_left.xml、slide_in_left.xml、slide_out_right.xml,然后在action中添加,如下:
    <fragment
        android:id="@+id/fragmentA"
        android:name="navigation.xxw.com.navigationdemo.FragmentA"
        android:label="fragment_a"
        tools:layout="@layout/fragment_a" >

        <action
            android:id="@+id/action_fragmentA_to_fragmentB"
            app:destination="@id/fragmentB"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right"/>
    </fragment>
  • 同樣也可以在代碼中通過設(shè)置NavOptions實現(xiàn),具體如下:
        val options = NavOptions.Builder()
                .setEnterAnim(R.anim.slide_in_right)
                .setExitAnim(R.anim.slide_out_left)
                .setPopEnterAnim(R.anim.slide_in_left)
                .setPopExitAnim(R.anim.slide_out_right)
                .build()

        view?.findViewById<Button>(R.id.btn_go_to_anim)?.setOnClickListener {
            Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB,null,options)
        }
  • 謝謝瀏覽!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,872評論 25 709
  • afinalAfinal是一個android的ioc,orm框架 https://github.com/yangf...
    wgl0419閱讀 6,575評論 1 9
  • 親愛的女兒: 7月16日,這天是你們高一新生到校軍訓(xùn)的第一天。海山學(xué)校依山傍海,風(fēng)景秀麗。校區(qū)座落在“石老人國家旅...
    陳虹_dd45閱讀 257評論 0 0
  • 今夜,月華如練 我望見她的鸞鏡朱顏 如花笑靨款款出現(xiàn) 夢中我曾見 天安門前的肅穆莊嚴 那一抹紅色染遍萬里江山 夢中...
    碧綠的心閱讀 270評論 0 0
  • 我是一枚妥妥滴六年級小學(xué)生,自從我五年級時家里發(fā)生了一些變故后,我就下載了一部看小說的軟件,迷上了它。 但是,...
    銀星海閱讀 3,469評論 0 0

友情鏈接更多精彩內(nèi)容