利用Navigation+fragment构建导航栏

androidx.fragment.app.FragmentContainerView

顾名思义,这是一个fragment的容器组件,如何使用?

在布局上创建,xml代码如下

<androidx.fragment.app.FragmentContainerView
   android:layout_width="match_parent"
   android:layout_height="0dp"
   android:id="@+id/nav_home_container"
   android:name="androidx.navigation.fragment.NavHostFragment"
   android:layout_weight="10"
   app:defaultNavHost="true"
   app:navGraph="@navigation/homepage"/>

name属性指它继承自这个NavHostFragment,一般来说,这个name属性必须有且值同样是这个NavHostFragment。

navGraph指内容,这个homepage是我们在/res/navigation/新建的,navigation同样是新建的,新建这个xml文件的很多步骤都是可以通过design模式设计的,可自行查询官方文档。

<?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/home"
   app:startDestination="@id/firstFragment">
   <fragment
       android:id="@+id/firstFragment"
       android:name="com.jay.navigation.fragment.FirstFragment"
       android:label="fragment_first"
       tools:layout="@layout/fragment_first" >
       <action
           android:id="@+id/action_first_to_second"
           app:destination="@id/secondFragment" />
   </fragment>
   <fragment
       android:id="@+id/secondFragment"
       android:name="com.jay.navigation.fragment.SecondFragment"
       android:label="fragment_second"
       tools:layout="@layout/fragment_second"/>

</navigation>

startDestination指起始的fragment。即刚打开这个activity,有这个fragment,起始就是这个指向的fragment。

action是一个动作,指从firstFragment前往secondFragment。可以根据destination这个属性判断,同样,这也可以在design模式直接设计。

动作自然不可能平白无故发生,所以我们可以设置一个按钮,点击按钮发生这个动作。

按钮写在起始的fragment的layout xml布局文件中,具体的绑定则要在所属的fragment文件中设置,会运用到navController这个组件,以下是绑定代码

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
   // Inflate the layout for this fragment

   View view = inflater.inflate(R.layout.fragment_first, container, false);
   view.findViewById(R.id.btn_to_second).setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
           NavController navController = Navigation.findNavController(view);
           navController.navigate(R.id.action_first_to_second);
      }
  });
   return view;
}

对于应用层来说,整个 Navigation 框架,我们只跟 NavController 打交道,它提供了常用的跳转、返回和获取返回栈等能力。

当然,要在xml布局文件中写入一个bottomNavigationView,这是下面的导航栏。

<com.google.android.material.bottomnavigation.BottomNavigationView
   android:layout_width="match_parent"
   android:layout_height="0dp"
   android:layout_weight="1"
   android:id="@+id/nav_home"
   android:background="@color/white"
   app:menu="@menu/menu_homepage_navigation"
   app:itemTextColor="@color/nav_home"
   app:itemIconTint="@color/nav_home"/>

itemTextColor、itemIconTint这两个属性可以设计选中和被选中的颜色。

在MainActivity获取NavController报错

问题原因就是在onCreate生命周期里FragmentContainerView对应的NavController未构建成功.

方法一:

使用getSupportFragmentManager获取

       NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
      mController = navHostFragment.getNavController();

方法二:

在onStart()生命周期里获取NavController

    @Override
  protected void onStart() {
      super.onStart();
      mController = Navigation.findNavController(MainActivity.this, R.id.fragment);
  }

将获取NavController的任务放到view创建测绘完成后在执行

        mBinding.fragment.post(new Runnable() {
          @Override
          public void run() {
              mController = Navigation.findNavController(SettingsActivity.this, R.id.nav_home_container);
          }
      });

绑定fragment容器和底部导航栏

使用navController.navigate()跳转到另一个fragment,这个方法中需要填入id。

注意:id是在这个navigation xml文件中设置的id,不是在fragment layout布局中设置的id

然后再将BottomNavigationView和这个navController绑定

mBottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
           @Override
           public boolean onNavigationItemSelected(@NonNull MenuItem item) {
               NavigationUI.onNavDestinationSelected(item, mNavController);
               return true;
          }
      });

注意如果使用监听器绑定,返回值为true,不然导航栏图标颜色动画不变

 

 

 

 

 

 

 

posted @ 2021-07-26 01:15  夏天了!好想睡觉  阅读(637)  评论(0)    收藏  举报