前面说了Navigation在做Activity跳转和Fragment跳转的时候,如何实现共享元素跳转的方式。这一篇,主要是说一下如何实现各大APP首页Tab切换的场景。
如何实现首页多个Tab使用Fragment的切换呢。
1、首先写布局。4个Fragment,这里省略冗余代码,仅展示一个fragment代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
android:gravity="center"
android:background="#3C84CC"
tools:context=".activity.NavigationMainActivity">
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="我是首页"
/>
</LinearLayout>
package com.github.navigationdemo.bottom
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.github.navigationdemo.R
import com.github.navigationdemo.databinding.FragmentHomeBinding
import com.github.navigationdemo.databinding.FragmentLoginBinding
import com.github.navigationdemo.databinding.FragmentRegisterBinding
class HomeFragment : Fragment() {
var _binding:FragmentHomeBinding?=null
val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return FragmentHomeBinding.inflate(inflater).also {
_binding=it
}.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
}
有了Fragment,那我们还需要有个放Fragment和展示Fragment的容器,这里,我们使用activity进行展示,先写布局。声明FragmentContainerView,作为Fragment的容器,BottomNavigationView作为跳转的控制器。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".activity.NavigationMainActivity">
<!--设置导航实现类,此处使用系统实现好的NavHostFragment
设置导航的资源图-->
<androidx.fragment.app.FragmentContainerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/navigation_container"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/nav_bottom_config"
app:defaultNavHost="true"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_nav_menu"/>
</LinearLayout>
BottomNavigationView是google封装好的,主要就是作为底部导航栏的封装控件,声明之后,需要配置menu菜单和数据。
bottom_nav_menu menu菜单数据
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/homeFragment"
android:title="首页"
android:icon="@drawable/baseline_home_24"
/>
<item android:id="@+id/secondFragment"
android:title="首页"
android:icon="@drawable/baseline_second_24"
/>
<item android:id="@+id/thirdFragment"
android:title="首页"
android:icon="@drawable/baseline_third_24"
/>
<item android:id="@+id/mineFragment"
android:title="首页"
android:icon="@drawable/baseline_mine_24"
/>
</menu>
<?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"
android:id="@+id/nav_bottom_config.xml"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.github.navigationdemo.bottom.HomeFragment"
android:label="HomeFragment" />
<fragment
android:id="@+id/secondFragment"
android:name="com.github.navigationdemo.bottom.SecondFragment"
android:label="SecondFragment" />
<fragment
android:id="@+id/mineFragment"
android:name="com.github.navigationdemo.bottom.MineFragment"
android:label="MineFragment" />
<fragment
android:id="@+id/thirdFragment"
android:name="com.github.navigationdemo.bottom.ThirdFragment"
android:label="ThirdFragment" />
</navigation>
重点:这里需要注意,navigation资源,和Menu资源的ID,要求是一样的,不然在之后运行的时候,控件内部,会出现因为找不到ID资源,而无法跳转的情况。
作为容器的Activity的代码实现。
package com.github.navigationdemo.bottom
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.github.navigationdemo.R
import com.github.navigationdemo.databinding.ActivityBottomNavigationBinding
class BottomNavigationActivity : AppCompatActivity() {
var binding :ActivityBottomNavigationBinding?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityBottomNavigationBinding.inflate(layoutInflater)
setContentView(binding?.root)
initView()
}
private fun initView() {
//方式一、通过使用NavHostFragment,与bottomNavigationView进行联动。是通过同一个navController进行控制。
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.navigation_container) as NavHostFragment
binding?.bottomNavView?.setupWithNavController(navHostFragment.navController)
}
}
这种方式是结合前面的内容,通过FragmentContainerView的方式进行实现的首页Tab切换效果。
2、接下来在介绍一个<fragment>标签实现tab切换效果的方式。(不推荐使用,但是有的老项目是这样用的,可能会遇到)
先改布局
<!--方式二布局-->
<fragment
android:id="@+id/navigation_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_bottom_config" />
再改实现方式
//方式二、通过fragment标签实现
binding?.bottomNavView?.setupWithNavController(findNavController(R.id.navigation_container))