在创建APP的基本框架的时候,最开始搭建的就是导航栏,然后往里塞东西,所以在创建导航栏时,有多种方式。
1、BottomNavigationBar + ViewPager + Fragment
这种方式 在之前项目中有介绍过,所以可以去翻之前的博客,这里就不再赘述。
2、BottomNavigationView + Fragment
这是JectPack组件出现之后,常用的一种导航栏模式,涉及到Navigation的用法,在之前的《JectPack组件开发3-----Navigation的用法》提及到。
首先在使用BottomNavigationView之前,先做一些准备工作。
(1)创建navigation文件
(2)创建menu菜单
menu菜单作为底部导航栏的资源。
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/first"
android:title="第一个"
android:icon="@drawable/ic_airline_seat_flat_angled_black_24dp"></item>
<item android:id="@+id/second"
android:title="第二个"
android:icon="@drawable/ic_airline_seat_flat_angled_black_24dp"></item>
<item android:id="@+id/third"
android:title="第三个"
android:icon="@drawable/ic_airline_seat_flat_angled_black_24dp"></item>
</menu>
(3)添加BottomNavigationView组件
需要设置底部导航的资源,并放到底部;左右点连接代表和父容器对齐,高度选择wrap_content。
(4)添加Fragment
高度选择match_constraint显示就是0dp
(5)设置导航
bottomNavigationView = findViewById(R.id.bottomNavigationView);
NavController controller = Navigation.findNavController(this,R.id.fragment);
//底部导航栏的配置
AppBarConfiguration configuration = new AppBarConfiguration.Builder(controller.getGraph()).build();
//这种方式不会有back的按键
AppBarConfiguration configuration = new AppBarConfiguration.Builder(bottomNavigationView.getMenu()).build();
NavigationUI.setupActionBarWithNavController(this,controller,configuration);
NavigationUI.setupWithNavController(bottomNavigationView,controller);
要注意的一点是:menu中每个Item的id一定要和每个Fragment的id一致,否则导航无法生效。
3、原始的RadioGruop + FrameLayout
在使用这种导航形式时,就需要使用Fragment事务管理,将Fragment添加到FrameLayout中显示。
private int currentIndex = 0;
private Fragment[] fragments;
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
firstFragment = new FirstFragment();
secondFragment = new SecondFragment();
thirdFragment = new ThirdFragment();
fragments = new Fragment[]{firstFragment,secondFragment,thirdFragment};
//把首页添加进去
transaction.add(R.id.fl_main,firstFragment).commit();
//默认选中第一个
select(currentIndex);
private void select(int index) {
if(currentIndex == index){
return;
}
//隐藏当前的Fragment
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.hide(fragments[currentIndex]);
if(!fragments[index].isAdded()){
ft.add(R.id.fl_main,fragments[index]);
}else{
ft.show(fragments[index]);
}
ft.commit();
currentIndex = index;
}
然后RadioGroup设置点击事件:
rg_main.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId){
case R.id.rb_first:
select(0);
break;
case R.id.rb_second:
select(1);
break;
case R.id.rb_third:
select(2);
break;
}
}
});
在开启Frgament事务之后,通过调用add
方法往容器中添加Fragment实例,显示在手机屏幕上,该方法需要在commit
之后才会生效;同样需要commit的是replace
,这种方法使用比较少,它是将容器中全部实例移除之后,在添加新的Fragment,因为Fragment不能重复添加,相当于执行remove
之后再执行add
,重新走一遍生命周期,所以也需要commit。
同一个事务只能被commit一次,commit方法是在装载Fragment容器的Activity调用onSaveInstanceState之前执行,因为onSaveInstanceState() 方法在 onStop() 方法之前执行,也是为了确保在Activity因为某些不可抗性导致进程被杀死,保存当前的状态;如果对Fragment的状态没有具体的要求,可以使用commitAllowingStateLoss()。
在实际的开发过程中,往往会使用add和hide或者show配合使用。Fragment的实例都在内存当中,只有当Fragment实例不存在时,才能添加Fragment到容器当中,所以当Fragment实例存在的时候,只需要调用show方法commit就可以显示Fragment;当需要隐藏该界面时,调用hide方法隐藏。
Fragment添加转场动画
(1)系统自带API
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
setTransition
是需要在add
或者remove
之前调用,使用FragmentTransaction
自带的一些动画。
(2)自定义View
@NonNull
public FragmentTransaction setCustomAnimations(@AnimatorRes @AnimRes int enter,
@AnimatorRes @AnimRes int exit) {
return setCustomAnimations(enter, exit, 0, 0);
}
通过设置setCustomAnimations
包括进场和退出的动画