最近手头上正在写的一个Android项目正好要用到底部导航栏,虽然受Android studio官方已经有一个底部导航栏的模板,但还是用自己熟悉的看着更舒服。接下来就记录一下用BottomNavigationBar实现底部导航栏的方法
添加依赖
在build.gradle文件的dependencies中增加如下代码,然后点击右上方sync,等待依赖文件添加完成
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.4'
布局中引入BottomNavigationBar
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/main_activity">
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</FrameLayout>
<com.ashokvarma.bottomnavigation.BottomNavigationBar
android:id="@+id/bottom_navigation_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"/>
</LinearLayout>
如上,我们首先添加一个Framelayout,之后我们将以它为容器装载切换的页面。当用户切换底部的tab时,导航至该tab对应的fragment。
创建每个TAB对应的fragment
比如我需要Home,Bluetooth,Hotspot三个页面,那就分别创建三个fragment以及相应的布局文件。取Home界面为例
public class HomeFragment extends Fragment {
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saveInstanceState){
view = inflater.inflate(R.layout.fragment_home, container, false);
return view;
}
}
布局文件
<?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=".fragment.HomeFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="主页" />
</FrameLayout>
这里只放了一个TextView用来指示是哪一个Fragment。
初始化BottomNavigationbar
在这里先放上MainActivity的完整源码
public class MainActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener{
/**
*初始化
*/
private Fragment mFragment;
private HomeFragment homeFragment;
private BlutoothFragment blutoothFragment;
private HotspotFragment hotspotFragment;
private FragmentTransaction transaction;
BottomNavigationBar bottomNavigationBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFragment();
bottomNavigationBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation_bar);
BottomNavigationBar();
bottomNavigationBar.setTabSelectedListener(this);
}
/**
* 初始化三个fragment,并将主页fragment加入事务中
*/
private void initFragment() {
homeFragment = new HomeFragment();
blutoothFragment = new BlutoothFragment();
hotspotFragment = new HotspotFragment();
transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fragment_container,homeFragment).commit();
mFragment = homeFragment;
}
/**
* 初始化底部导航栏样式
*/
private void BottomNavigationBar(){
bottomNavigationBar.setActiveColor(R.color.colorAccent)
.setInActiveColor(R.color.colorPrimary)
.setBarBackgroundColor("#FFFFFF");
bottomNavigationBar.setMode(BottomNavigationBar.MODE_FIXED);
//背景样式
bottomNavigationBar.addItem(new BottomNavigationItem(R.drawable.ic_home, "主页").setActiveColorResource(R.color.blue))
.addItem(new BottomNavigationItem(R.drawable.ic_bluetooth, "蓝牙模式").setActiveColorResource(R.color.blue))
.addItem(new BottomNavigationItem(R.drawable.ic_hotspot, "热点模式").setActiveColorResource(R.color.blue))
.setFirstSelectedPosition(0)
.initialise();
}
/**
* TAB被点击时的切换fragment
* @param position
*/
@Override
public void onTabSelected(int position) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
switch(position){
case 0:
switchFragment(homeFragment);
break;
case 1:
switchFragment(blutoothFragment);
break;
case 2:
switchFragment(homeFragment);
break;
default:
switchFragment(homeFragment);
break;
}
transaction.commit();
}
@Override
public void onTabUnselected(int position) { }
@Override
public void onTabReselected(int position) { }
/**
* 切换fragment的方法
* @param fragment
*/
private void switchFragment(Fragment fragment) {
//判断当前显示的Fragment是不是切换的Fragment
if(mFragment != fragment) {
//判断切换的Fragment是否已经添加过
if (!fragment.isAdded()) {
//如果没有,则先把当前的Fragment隐藏,把切换的Fragment添加上
getSupportFragmentManager().beginTransaction().hide(mFragment)
.add(R.id.fragment_container,fragment).commit();
} else {
//如果已经添加过,则先把当前的Fragment隐藏,把切换的Fragment显示出来
getSupportFragmentManager().beginTransaction().hide(mFragment).show(fragment).commit();
}
mFragment = fragment;
}
}
}
解释一下上述代码。
在initFragment()方法中,首先初始化各个fragment,然后用一个FragmentTransaction来对这些fragment进行管理。其中mFragment是用来指示当前TAB所指向的fragment。我们将主页HomeFragment的实例作为提交的第一个事务。
在BottomNavigationBar()中我们设置底部导航栏的样式,被选中时的颜色,未选中时的颜色,背景。通过addItem添加底部的TAB,设置对应的每个TAB的背景图片和文字。
实现BottomNavigationBar.OnTabSelectedListener接口,重写其onTabSelected方法,用以点击不同TAB时切换到不同fragment。
switchFragment()方法中,为了防止fragment 被重复创建,所以用isAdded方法做一个判断,若添加过,切换时只需将其隐藏,然后展示需要的fragment即可。若没有,则先将所需fragment增加到事务中提交。