• 【jetpack】Navigation


    ❤️ Author: 老九
    ☕️ 个人博客:老九的CSDN博客
    🙏 个人名言:不可控之事 乐观面对
    😍 系列专栏:

    Navigation

    • 可以在Fragment中进行跳转或者传值,不需要用intent的了,这样可以实现一个Activity通过Navigation在无数个Fragment中进行跳转
    • 首先在res中创建navigation文件夹,创建一个nav_graph.xml的文件
      在这里插入图片描述
    • 点击那个绿色的加号,从而添加Fragment页面,添加两个Fragment1和Fragment2
    • id对应的是Fragment对应的名字,name是对应的Fragment的全类名,label是和toolbar联动的时候使用的,layout是和Fragment布局文件所对应的
    • Navigation有自己的id,startDestination是默认启动的目的地
    • 当我们在可视化中拉出一个箭头之后,就会出现一个action标签,destination是目的地的id
    <?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/nav_grapph"
        app:startDestination="@id/fragment1">
    
        <fragment
            android:id="@+id/fragment1"
            android:name="com.example.anew.Fragment1"
            android:label="fragment_home"
            tools:layout="@layout/fragment_1" >
            <action
                android:id="@+id/action_fragment1_to_fragment2"
                app:destination="@id/fragment2"
                app:enterAnim="@android:anim/fade_in"
                app:exitAnim="@android:anim/fade_out"
                app:popEnterAnim="@android:anim/slide_in_left"
                app:popExitAnim="@android:anim/slide_out_right" />
        </fragment>
        <fragment
            android:id="@+id/fragment2"
            android:name="com.example.anew.Fragment2"
            android:label="fragment_2"
            tools:layout="@layout/fragment_2" >
            <argument
                android:name="name"
                app:argType="string"
                android:defaultValue="marry" />
            <argument
                android:name="age"
                app:argType="integer"
                android:defaultValue="10"/>
        </fragment>
        <fragment
            android:id="@+id/blankFragment"
            android:name="com.example.anew.BlankFragment"
            android:label="fragment_blank"
            tools:layout="@layout/fragment_blank" />
    </navigation>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • Fragment1对应的xml文件
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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"
        android:orientation="vertical"
        tools:context=".Fragment1">
    
        <!-- TODO: Update blank fragment layout -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="30sp"
            android:layout_gravity="clip_horizontal"
            android:layout_marginTop="30dp"
            android:text="HOME" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:layout_gravity="center_horizontal"
            android:text="跳转"/>
    
    </LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • Fragment2对应的xml文件
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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"
        android:orientation="vertical"
        tools:context=".Fragment2">
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            android:layout_gravity="center_horizontal"
            android:text="@string/hello_blank_fragment" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/button2"
            android:text="button"/>
    
    </LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 接着我们要在activity.xml中放置一个navigation的容器,去承载fragment,在可视化中叫做NavHostFragment
    • navgraph关联我们刚才写的导航图
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
    
    
        <fragment
            android:id="@+id/fragmentContainerView"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="409dp"
            android:layout_height="729dp"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_grapph"
            tools:layout_editor_absoluteX="1dp"
            tools:layout_editor_absoluteY="1dp"
            tools:ignore="MissingConstraints" />
    
    </fragment>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 接着在Activity类中我们不需要做任何处理,但是在Fragment1中,我们需要设置点击事件
    • 我们使用findNavController作为导航的控制器,这里使用了扩展函数,之后我们调用Navigate函数,传入action的id,就可以实现跳转啦
    package com.example.anew
    
    import android.os.Bundle
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.Button
    import androidx.fragment.app.Fragment
    import androidx.navigation.findNavController
    
    class Fragment1 : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_1, container, false)
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            val button: Button = view.findViewById<Button>(R.id.button)
            button.setOnClickListener {
    //            val bundle = Bundle()
    //            bundle.putString("name", "jack")
                val controller = it.findNavController()
                controller.navigate(R.id.action_fragment1_to_fragment2)
            }
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 这里有一个情况,就是实现跳转的时候是放在返回栈中,如果要是想把fragment2在返回栈中弹出,需要调用popBackstack的方法。
    package com.example.anew
    
    import android.os.Bundle
    import androidx.fragment.app.Fragment
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.Button
    import android.widget.TextView
    import androidx.navigation.findNavController
    
    class Fragment2 : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_2, container, false)
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            val button2 : Button = view.findViewById<Button>(R.id.button2)
            button2.setOnClickListener{
                it.findNavController().popBackStack()
            }
    //        val tv_name : TextView = view.findViewById(R.id.tv_name)
    //        tv_name.text = arguments?.getString("name")
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    Navigation的数据传递

    • 有两种方式,第一种方式是创建Bundle,通过putString传值,然后navigate中有一个重载的函数是可以接受到bundle的
    package com.example.anew
    
    import android.os.Bundle
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.Button
    import androidx.fragment.app.Fragment
    import androidx.navigation.findNavController
    
    class Fragment1 : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_1, container, false)
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            val button: Button = view.findViewById<Button>(R.id.button)
            button.setOnClickListener {
                val bundle = Bundle()
                bundle.putString("name", "jack")
                val controller = it.findNavController()
                controller.navigate(R.id.action_fragment1_to_fragment2, bundle)
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 然后在Fragment中,使用setarguments获得值
    package com.example.anew
    
    import android.os.Bundle
    import androidx.fragment.app.Fragment
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.Button
    import android.widget.TextView
    import androidx.navigation.findNavController
    
    class Fragment2 : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_2, container, false)
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            val button2 : Button = view.findViewById<Button>(R.id.button2)
            button2.setOnClickListener{
                it.findNavController().popBackStack()
            }
            val tv_name : TextView = view.findViewById(R.id.tv_name)
            tv_name.text = arguments?.getString("name")
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 第二种方式是在Navigation中的arguments修改
    • 我们在Fragment2中,添加argument标签
    <?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/nav_grapph"
        app:startDestination="@id/fragment1">
    
        <fragment
            android:id="@+id/fragment1"
            android:name="com.example.anew.Fragment1"
            android:label="fragment_home"
            tools:layout="@layout/fragment_1" >
            <action
                android:id="@+id/action_fragment1_to_fragment2"
                app:destination="@id/fragment2"
                app:enterAnim="@android:anim/fade_in"
                app:exitAnim="@android:anim/fade_out"
                app:popEnterAnim="@android:anim/slide_in_left"
                app:popExitAnim="@android:anim/slide_out_right" />
        </fragment>
        <fragment
            android:id="@+id/fragment2"
            android:name="com.example.anew.Fragment2"
            android:label="fragment_2"
            tools:layout="@layout/fragment_2" >
            <argument
                android:name="name"
                app:argType="string"
                android:defaultValue="marry" />
            <argument
                android:name="age"
                app:argType="integer"
                android:defaultValue="10"/>
        </fragment>
        <fragment
            android:id="@+id/blankFragment"
            android:name="com.example.anew.BlankFragment"
            android:label="fragment_blank"
            tools:layout="@layout/fragment_blank" />
    </navigation>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 然后在Fragment2中编写代码,测试是否收到了默认值
    package com.example.anew
    
    import android.os.Bundle
    import androidx.fragment.app.Fragment
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.Button
    import android.widget.TextView
    import androidx.navigation.findNavController
    
    class Fragment2 : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_2, container, false)
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            val button2 : Button = view.findViewById<Button>(R.id.button2)
            button2.setOnClickListener{
                it.findNavController().popBackStack()
            }
            val tv_name : TextView = view.findViewById(R.id.tv_name)
            tv_name.text = arguments?.getString("name")+arguments?.getString("age")
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    Navigation与顶部导航栏关联

    • 首先在Activity中找到navigation的controller,其次创建一个appbarconfiguration对象,把controller的导航图传到这个appbar的文件里面,之后将controller和appbar进行关联
    package com.example.anew
    
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.util.Log
    import android.util.Log.*
    import androidx.appcompat.widget.Toolbar
    import androidx.navigation.NavController
    import androidx.navigation.findNavController
    import androidx.navigation.ui.AppBarConfiguration
    import androidx.navigation.ui.setupActionBarWithNavController
    import androidx.navigation.ui.setupWithNavController
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            //找到当前fragment 的controller
             var controller: NavController = findNavController(R.id.fragment)
            //获得actionbar的控件
            val appBarConfiguration = AppBarConfiguration(controller.graph)
            //将他俩关联起来
    setupActionBarWithNavController(controller,appBarConfiguration)
     //controller.addOnDestinationChangedListener { controller, destination, arguments ->
    //            Log.e("zdd",destination.toString())
    //            Log.e("zdd",arguments.toString())
    //        }
        //处理系统activity的home点击事件代码
        override fun onSupportNavigateUp(): Boolean {
            var controller: NavController = findNavController(R.id.fragment)
            return controller.navigateUp()||super.onSupportNavigateUp()
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 我们可以通过setupWithNavController方法,进行自定义Toolbar,之后进行一系列的动作
    val toolbar : Toolbar = findViewById(R.id.toolbar)
            toolbar.setupWithNavController(controller,appBarConfiguration)
    
    • 1
    • 2
    • 底部导航栏,有相应的模板,在Activity中有一个Bottom Navigation activity
      在这里插入图片描述
    • 然后在nav_graph.xml中加入如下代码,进行关联
     <activity
            android:id="@+id/main2Activity"
            android:name="com.example.anew.Main2Activity"
            android:label="Main2Activity" />
    
    • 1
    • 2
    • 3
    • 4
    • 之后在Fragment2中创建两个button,修改Fragment2的代码
    package com.example.anew
    
    import android.os.Bundle
    import androidx.fragment.app.Fragment
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.Button
    import android.widget.TextView
    import androidx.navigation.findNavController
    
    class Fragment2 : Fragment() {
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_2, container, false)
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            val button2 : Button = view.findViewById<Button>(R.id.button2)
            button2.setOnClickListener{
                it.findNavController().navigate(R.id.action_fragment2_to_mobile_navigation)
            }
            val button3 : Button = view.findViewById<Button>(R.id.button3)
            button3.setOnClickListener{
                it.findNavController().navigate(R.id.action_fragment2_to_main2Activity)
            }
            val tv_name : TextView = view.findViewById(R.id.tv_name)
            tv_name.text = arguments?.getString("name")+arguments?.getInt("age")
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • Main2Activity中的代码
    package com.example.anew
    
    import android.os.Bundle
    import com.google.android.material.bottomnavigation.BottomNavigationView
    import androidx.appcompat.app.AppCompatActivity
    import androidx.navigation.findNavController
    import androidx.navigation.ui.AppBarConfiguration
    import androidx.navigation.ui.setupActionBarWithNavController
    import androidx.navigation.ui.setupWithNavController
    import com.example.anew.databinding.ActivityMain2Binding
    
    class Main2Activity : AppCompatActivity() {
    
        private lateinit var binding: ActivityMain2Binding
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            binding = ActivityMain2Binding.inflate(layoutInflater)
            setContentView(binding.root)
            supportActionBar?.hide()
            val navView: BottomNavigationView = binding.navView
    
            val navController = findNavController(R.id.nav_host_fragment_activity_main2)
            // Passing each menu ID as a set of Ids because each
            // menu should be considered as top level destinations.
            val appBarConfiguration = AppBarConfiguration(
                setOf(
                    R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications
                )
            )
            //绑定底下的类似于bar的东西
            setupActionBarWithNavController(navController, appBarConfiguration)
            //处理点击跳转
            navView.setupWithNavController(navController)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    ————————————————————————
    ♥♥♥码字不易,大家的支持就是我坚持下去的动力♥♥♥
    版权声明:本文为CSDN博主「亚太地区百大最帅面孔第101名」的原创文章

  • 相关阅读:
    Day7:浅谈useEffect
    AndroidTV开发12——大屏TV电视及盒子Apk远程安装说明文档
    jQuery笔记一
    机器学习 | MATLAB实现MLP多层感知机模型设计
    如何在在线Excel文档中规范单元格输入
    学生成绩管理系统(C语言课设 )
    Linux实用指令-指定运行级别、帮助指令
    elasticsearch,为什么prefix性能消耗很大
    Linxu重新获取IP地址
    【C语言】操作符详解
  • 原文地址:https://blog.csdn.net/partworld/article/details/126348767