Android Jetpack套件之Navigation導航組件

首先記錄一個坑:no current navigation node

06-26 14:42:25.787 25913-25913/com.bluetree.bytepay2 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.bluetree.bytepay2, PID: 25913
    java.lang.IllegalStateException: no current navigation node
        at androidx.navigation.NavController.navigate(NavController.java:764)
        at androidx.navigation.NavController.navigate(NavController.java:744)
        at androidx.navigation.NavController.navigate(NavController.java:730)
        at androidx.navigation.NavController.navigate(NavController.java:718)
        at com.bluetree.bytepay2.sample.BlankFragment$1.onClick(BlankFragment.java:83)
        at android.view.View.performClick(View.java:5264)
        at android.view.View$PerformClick.run(View.java:21297)
        at android.os.Handler.handleCallback(Handler.java:743)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:150)
        at android.app.ActivityThread.main(ActivityThread.java:5546)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)

解決方案:navigation.xml 中的Fragment繼承了NavHostFragment,取消繼承就可以了!

Navigation導航組件

概述

Navigation是什麼,有什麼意義,內涵之類的這裏就不展開篇幅講了,能貼圖片絕不多說半句廢話。這篇文章只做一個引入的Navigation的用途,適合新手上路。簡單來說,可以用Navigation來進行一些簡單的,並直觀的頁面跳轉。

 

使用步驟

引入庫就不提,因爲當你使用到Navigation的時候,AS會自動幫你導入的,下面簡單介紹一下如何使用Navigation

  1. 創建navigation目錄
  2. 創建navigation.xml文件
  3. 首先創建一個簡單的Activity(SampleNavigationActivity)
  4. 在佈局文件(R.layout.activity_sample_navigation)中引入androidx.navigation.fragment.NavHostFragment
  5. 創建兩個普通的Fragment(BlankFragment1,BlankFragment2)
  6. 打開navigation.xml,把兩個fragment添加進去。用箭頭直觀地展示跳轉邏輯。
  7. 通過一句代碼實現跳轉邏輯

 

具體實現

 

創建navigation目錄

res右鍵選擇新建資源目錄

 

創建navigation資源文件

navigation目錄右鍵,如圖依次選擇

<?xml version="1.0" encoding="utf-8"?>
<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/navigation"
>
<!--todo 添加fragment進行愉快地拖拽-->

</navigation>

新建activity

public class SampleNavigationActivity extends AppCompatActivity  {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample_navigation);
    }
}

佈局文件中添加navigation容器

如下圖,引入NavHostFragment,app:defaultNavHost設置默認的navigation文件,並且攔截返回事件

app:navGraph用於指定navigation.xml文件

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".sample.SampleNavigationActivity">

    <fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/navigation" />

</FrameLayout>

創建n個Fragment用於切換

Fragment2也是一樣的,這裏不重複寫了

private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 *
 */
class BlankFragment1 : Fragment() {

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
       
    }

}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".sample.BlankFragment1">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />
</FrameLayout>

 

打開navigation.xml,把兩個fragment添加進去,愉快地用箭頭直觀地展示跳轉邏輯

添加左上角的new destination 添加目標界面,然後就可以愉快地玩耍了

 

通過一句代碼實現跳轉邏輯

通過上面的步驟已經規劃好了,最後需要用代碼來觸發跳轉,例如由Fragment1點擊按鈕跳轉到Fragment2,則我們需要編輯Fragment1的按鈕點擊事件來完成這個邏輯,修改Fragment1的代碼如下

class BlankFragment1 : Fragment() {

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<Button>(R.id.btn).setOnClickListener {
            //實現跳轉
            Navigation.findNavController(getView()!!).navigate(R.id.action_blankFragment1_to_blankFragment2)
        }
    }

}

拓展

 

總結

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章