底部导航栏实现方式多样化

前沿   距Google I/O(2014)最新发布的Material Design Android 设计风格已经有一段时间了, 2016年Google在 Android Design Support Library 25基础上增加了 一个BottomNavigationView 新控件,
相比之前实现导航栏的方式,如LinearLayout + TextView(使用android:drawableTop属性+selector状态切换)、
LinearLayout + RelativeLayout(TextView+ImageView)
RadioGroup + RadioButton,2015年Google推出的兼容包Android Design Support Library中的TabLayout等
该控件提供更简洁的方式实现功能模块导航,符合材料设计规范,
效果图如下:



BottomNavigationView 继承自 FrameLayout 对外暴露了OnNavigationItemSelectedListener接口,便于对子视图点击事件的处理,可以通过此接口动态
改变文字颜色   图标颜色;
在XML需要了解其以下属性  (记得添加  xmlns:app="http://schemas.android.com/apk/res-auto")
app:itemIconTint : 设置图标着色 
app:itemTextColor : 设置文本颜色  
app:menu : 设置菜单 
app:itemBackground : 设置导航栏的背景色


默认该控件图标、文本都使用系统自带的@color/colorPrimary颜色

需要注意的是源码中明确指出最大子View个数不能超过5个,在子View个数大于等于4的时候  只有选中的显示文字,没有选中的只显示图标

并且会显示自带的动画,貌似看起来有些浮夸,在源码BottomNavigationMenuView中,有一个全局变量:mShiftingMode,
private boolean mShiftingMode = true;在创建、更新Menu的时候调用了buildMenuView()方法 

public void buildMenuView() {
    ...
    mShiftingMode = mMenu.size() > 3;
    ...
}

具体效果图如下:



下面使用BottomNavigationView+ViewPager+Fragment组合实现 导航展示界面  真机5.0.2测试

使用前打开build.gradle 添加依赖

//可以修改为你项目中对应的版本号  建议修改与    compile 'com.android.support:appcompat-v7:25.0.0'  相同的版本号 
    compile 'com.android.support:design:25.0.0'

首先在Res目录下创建一个menu文件夹,并新建一个activity_main_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">


<item
    android:id="@+id/home"
    android:icon="@drawable/ic_home_white_24dp"
    android:title="首页" />


    <item
        android:id="@+id/love"
        android:icon="@drawable/ic_favorite_white_24dp"
        android:title="喜欢" />
    <item
        android:id="@+id/video"
        android:icon="@drawable/ic_videogame_asset_white_24dp"
        android:title="视频" />


    <item
        android:id="@+id/book"
        android:icon="@drawable/ic_book_white_24dp"
        android:title="订阅" />


    <item
        android:id="@+id/github"
        android:icon="@drawable/ic_github_circle_white_24dp"
        android:title="Github" />


</menu>

MainActivity XML定义如下:


<?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="com.createfuture.android.md50.MainActivity">


    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.9" />


    <android.support.design.widget.BottomNavigationView
        android:id="@+id/main_bottom_nav_bar"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.1"
        android:background="@android:color/white"
        app:itemIconTint="#be4c00"
        app:itemTextColor="#be4c00"
        app:menu="@menu/activity_main_bottom"
        />


</LinearLayout>




BaseActivity基类简单封装如下:

public abstract  class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutViewId());
        //initView
        initView();
        //initData
        initData();
        //initListener
        initListener();
    }


    protected abstract void initListener();


    protected abstract void initData();


    protected abstract void initView();


    // UI  View Layout
    protected abstract    @LayoutRes  int getLayoutViewId();


    //get View ID
    public <T extends  View> T getViewId(int id){
        View view=getWindow().getDecorView().findViewById(id);
        return (T) view;
    }

}

MainActivity代码如下:

package com.createfuture.android.guidenavigationbar;


import android.annotation.SuppressLint;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.createfuture.android.md50.R;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends BaseActivity implements BottomNavigationView.OnNavigationItemSelectedListener,
        ViewPager.OnPageChangeListener {

    private ViewPager viewPager;//实现左右滑动的ViewPager


    private BottomNavigationView bottomNavigationView;//底部导航栏


    private List<Fragment> myFragment = new ArrayList<>();//存放Fragment集合

    private String[] mTiltls = new String[]{"首页", "喜欢", "视频", "订阅", "Github"};

    private long currentTime = 0;


    @Override
    protected int getLayoutViewId()

    {
        return R.layout.activity_main;
    }

    @Override
    protected void initView() {
        bottomNavigationView = getViewId(R.id.main_bottom_nav_bar);
        //设置背景色
        bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffffbb33")));

        //禁用模式
   disableShiftMode(bottomNavigationView);
        //设置默认选中最后一个
        bottomNavigationView.setSelectedItemId(R.id.github);

        viewPager = getViewId(R.id.viewPager);
        //可以设置ViewPager禁止滑动
        //禁止ViewPager滑动
        viewPager.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });

    }
    /**  *  * 如何禁用ShiftingMode这种模式,stackoverflow上面找到解决办法:反射:  * <a href="https://stackoverflow.com/questions/40176244/how-to-disable-bottomnavigationview-shift-mode">禁用</a>.  */   @SuppressLint("RestrictedApi")
    public  void disableShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        try {
            Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
            shiftingMode.setAccessible(true);
            shiftingMode.setBoolean(menuView, false);
            shiftingMode.setAccessible(false);
            for (int i = 0; i < menuView.getChildCount(); i++) {
                BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
                //noinspection RestrictedApi
                item.setShiftingMode(false);
                // set once again checked value, so view will be updated
                //noinspection RestrictedApi
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (NoSuchFieldException e) {
            Log.e("shiftingMode", "Unable to get shift mode field", e);
        } catch (IllegalAccessException e) {
            Log.e("shiftingMode", "Unable to change value of shift mode", e);
        }
    }
    /**  * 初始化底部导航栏数据 Fragment集合 并配置适配器  */  @Override
    protected void initData() {


        for (int i = 0; i < mTiltls.length; i++) {
            myFragment.add(TestFragment.getInstance(mTiltls[i]));
        }

        viewPager.setAdapter(new CustomPagerAdapter(getSupportFragmentManager()));
        viewPager.setCurrentItem(4);
    }


    @Override
    protected void initListener() {
        bottomNavigationView.setOnNavigationItemSelectedListener(this);
        viewPager.setOnPageChangeListener(this);
    }


    /**  * @param item 获取到MenuItem Id  * @return 返回true 显示选中效果 反之不会显示  */  @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        //
        int itemId = item.getItemId();
        switch (itemId) {
            case R.id.home:
                viewPager.setCurrentItem(0);
                break;
            case R.id.love:
                viewPager.setCurrentItem(1);
                break;

            case R.id.video:
                viewPager.setCurrentItem(2);
                break;


            case R.id.book:
                viewPager.setCurrentItem(3);
                break;


            case R.id.github:
                viewPager.setCurrentItem(4);
                break;

        }

        return true;

    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    /**  * 选中的效果  * //API 21 及其以上才可以设置setBackgroundTintList  * @param position  */  @SuppressLint("ResourceAsColor")
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onPageSelected(int position) {
        switch (position) {

            case 0:
                bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffff8800")));

                bottomNavigationView.setSelectedItemId(R.id.home);
                break;


            case 1:
                bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ff99cc00")));

                bottomNavigationView.setSelectedItemId(R.id.love);
                break;


            case 2:

                bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ff0099cc")));
                bottomNavigationView.setSelectedItemId(R.id.video);
                break;


            case 3:
                bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.GRAY));

                bottomNavigationView.setSelectedItemId(R.id.book);
                break;

            case 4:
                bottomNavigationView.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#ffffbb33")));

                bottomNavigationView.setSelectedItemId(R.id.github);
                break;
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }


    //ViewPager Adapter  真正开发  记得要新建一个类,尽可能的少用内部类
    private class CustomPagerAdapter extends FragmentPagerAdapter {


        public CustomPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return myFragment == null ? null : myFragment.get(position);
        }

        @Override
        public int getCount() {
            return myFragment.size() == 0 ? 0 : myFragment.size();
        }
    }

    /**  * 监听返回键  */  @Override
    public void onBackPressed() {

        if (viewPager.getCurrentItem() != 0) {
            viewPager.setCurrentItem(0);
        } else {
            exit();

        }

    }

    //退出
    private void exit() {
        if (System.currentTimeMillis() -currentTime >2000) {
            currentTime = System.currentTimeMillis();
            Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();


        } else {
            finish();
        }
    }




}




TestFragment代码如下:

package com.createfuture.android.guidenavigationbar;


import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**  * Created by GuoBin on 2017/12/23.  */   public  class TestFragment  extends Fragment {
     //静态常量标识
     private  final   static  String KEY=TestFragment.class.getSimpleName();



     public  static Fragment   getInstance(String textContent){
         /**  * 实例化当前Fragment 并初始化Bundle 保存数据到Fragment,用于Fragment界面文本展示  */  TestFragment fragment=new TestFragment();

         Bundle bundle=new Bundle();
         bundle.putString(KEY,textContent);
         fragment.setArguments(bundle);
         return  fragment;
     }

    /**  * 加载视图  * @param inflater  * @param container  * @param savedInstanceState  * @return  */  @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        /**  * 布局文件通过动态生成 首先新建一个 RelativeLayout,设置宽高属性  * 同理新建一个TextView,设置宽高属性,并设置文本  * 将TextView添加到RelativeLayout中  */  RelativeLayout relativeLayout=new RelativeLayout(getContext().getApplicationContext());

        RelativeLayout.LayoutParams   layoutParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

        relativeLayout.setLayoutParams(layoutParams);


        TextView textView=new TextView(getContext().getApplicationContext());

        textView.setLayoutParams(layoutParams);

        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(23);
        textView.setTextColor(Color.BLACK);
        textView.setText(getArguments().getString(KEY)!=null?getArguments().getString(KEY).toString():"");


        relativeLayout.addView(textView);


        return relativeLayout;
    }
}



官方的BottomNavigationView的item个数大于4个的时候会自动的改变显示模式,
隐藏了文字,相比之下,下面的导航栏就没有这个问题,而且功能更全。


目前github开源了几个好用的控件,

第一个:外国开源 https://github.com/aurelhubert/ahbottomnavigation
下面是包含的开源文件

AHNotification.java


AHNotificationHelper.java


AHBottomNavigation.java  
AHBottomNavigationAdapter.java
AHBottomNavigationBehavior.java
AHBottomNavigationFABBehavior.java
AHBottomNavigationItem.java
AHBottomNavigationViewPager.java
AHHelper.java
VerticalScrollingBehavior.java
...

可以实现消息角标提示等效果,如图:




第二个:外国开源https://github.com/Ashok-Varma/BottomNavigation

 封装了好多东西   里面包含有角标 ,可以实现消息提示


behaviour文件包含  BottomNavBarFabBehaviour.java
BottomVerticalScrollBehavior.java
VerticalScrollingBehavior.java

utils文件夹中包含如下:
BadgeItem.java
BottomNavigationBar.java
BottomNavigationHelper.java
BottomNavigationItem.java
BottomNavigationTab.java
FixedBottomNavigationTab.java
ShapeBadgeItem.java2.0.1 released
ShiftingBottomNavigationTab.java
TextBadgeItem.java


效果图:





第三个:外国开源
https://github.com/armcha/LuseenBottomNavigation
实现效果跟官方的类似
包含文件:


..
BottomNavigationItem.java
BottomNavigationUtils.java
BottomNavigationView.java
OnBottomNavigationItemClickListener.java


实现效果与官方类似,这里不贴图。


主要说一下第一个开源实现案例 自定义ViewPager+底部导航栏AHBottomNavigation+自定义Fragment实现

  首先引入依赖  

  compile 'com.aurelhubert:ahbottomnavigation:2.1.0'
   compile 'com.android.support:design:25+'


  注意:如果想实现如图所示的效果,需要在页面中添加一个上下滑动的列表,如果不是RecyclerView,没有上下联动效果,
如果想自己实现,可以继承CoordinatorLayout.Behavior<V> ,重写必要的方法实现

RecyclerView对应的适配器 MyAdapter代码如下:

package com.createfuture.android.aurelhubertahbottomnavigation;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;

/**  * RecyclerView列表适配器  */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    //集合
    private ArrayList<String> mDataset = new ArrayList<>();


    //数据入口
    public MyAdapter(ArrayList<String> dataset) {
        mDataset.clear();
        mDataset.addAll(dataset);
    }

    /**  * 创建视图  *  * @param parent  * @param viewType  * @return  */  @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item_demo, parent, false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    /**  * 绑定数据到 TextView  *  * @param holder  * @param position  */  @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(mDataset.get(position));

    }

    /**  * 获取集合大小  *  * @return  */  @Override
    public int getItemCount() {
        return mDataset.size();
    }


    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;

        public ViewHolder(View v) {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.layout_item_demo_title);
        }
    }
}

列表子视图layout_item_demo.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:orientation="vertical"

    android:layout_margin="8dp">


    <TextView
        android:id="@+id/layout_item_demo_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="16dp"
        android:textColor="#212121"
        android:textSize="18sp" />


</RelativeLayout>


自定义一个Fragment  起名为TestFragment 对应布局文件(fragment_demo_list.xml)如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/fragment_container"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/fragment_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>


TestFragment文件内容:

package com.createfuture.android.aurelhubertahbottomnavigation;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;


/**  * Created by GuoBin on 2017/12/23.  */  public class TestFragment extends Fragment {
    //RecyclerView
    private RecyclerView recyclerView;

    //RecyclerView.LayoutManager
    private RecyclerView.LayoutManager layoutManager;

    //静态常量标识
    private final static String KEY = TestFragment.class.getSimpleName();

    //列表适配器
    private MyAdapter mAdapter;

    /**  * 获得带有数据的TestFragment实类  * @param content  * @return  */  public static Fragment getInstance(String content) {
        /**  * 实例化当前Fragment 并初始化Bundle 保存数据到Fragment,用于Fragment界面文本展示  */  TestFragment fragment = new TestFragment();

        Bundle bundle = new Bundle();
        bundle.putString(KEY, content);
        fragment.setArguments(bundle);

        return fragment;
    }

//加载布局
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_demo_list, container, false);
        initDemoList(view);

        return view;
    }

    private void initDemoList(View view) {
        recyclerView = (RecyclerView) view.findViewById(R.id.fragment_recycler_view);

        layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);
//初始化数据
        ArrayList<String> itemsData = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            itemsData.add("Fragment " + getArguments().get(KEY));
        }

        mAdapter = new MyAdapter(itemsData);
        recyclerView.setAdapter(mAdapter);



    }
}


  MainActivity对应的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.aurelhubert.ahbottomnavigation.AHBottomNavigationViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floating_action_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|bottom"
        android:layout_marginBottom="88dp"
        android:src="@mipmap/ic_content_add"

        app:useCompatPadding="true"/>

    <com.aurelhubert.ahbottomnavigation.AHBottomNavigation
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:selectedBackgroundVisible="false"/>

</android.support.design.widget.CoordinatorLayout>





MainActivity对应的代码如下:

package com.createfuture.android.aurelhubertahbottomnavigation;

import android.animation.Animator;
import android.graphics.Color;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.OvershootInterpolator;

import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationViewPager;
import com.aurelhubert.ahbottomnavigation.notification.AHNotification;

import java.util.ArrayList;
import java.util.List;

/**  * CoordinatorLayout+底部导航栏+自定义A HBottomNavigationViewPager+Fragment  * 实现如图效果  */ public class MainActivity extends AppCompatActivity  implements  AHBottomNavigation.OnTabSelectedListener{
    //UI元素
    private AHBottomNavigationViewPager viewPager;//自定义ViewPager
    private AHBottomNavigation bottomNavigation;//底部导航栏
    private FloatingActionButton floatingActionButton;//悬浮按钮

    //Fragment集合
   private  List<Fragment> myFragment=new ArrayList<>();
   //底部导航栏标题
    private String[] mTiltls = new String[]{"Menu1", "Menu2", "Menu3", "Menu4", "Menu5"};
    //底部导航栏子项集合
    private ArrayList<AHBottomNavigationItem> bottomNavigationItems = new ArrayList<>();
   //消息通知
  private AHNotification notification;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initData();
        initListener();
    }
    //初始化控件
    private void initView() {
        bottomNavigation = (AHBottomNavigation) findViewById(R.id.bottom_navigation);
        //选中的图标着色以及文本的颜色
        bottomNavigation.setAccentColor(Color.RED);
        //没有选中的图标着色以及文本的颜色
        bottomNavigation.setInactiveColor(Color.BLACK);
        //去除隐藏标题的状态
        bottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW);

        viewPager = (AHBottomNavigationViewPager) findViewById(R.id.view_pager);
        viewPager.setPagingEnabled(false);//禁止滑动
        floatingActionButton = (FloatingActionButton) findViewById(R.id.floating_action_button);
       //管理Floating的显示行为

        bottomNavigation.manageFloatingActionButtonBehavior(floatingActionButton);
        //交互行为可用
       // bottomNavigation.setBehaviorTranslationEnabled(true);
    }
    //初始化数据
    private void initData() {

        /**  * 为导航栏添加带图标的文字  */  AHBottomNavigationItem item1 = new AHBottomNavigationItem(mTiltls[0], R.mipmap.ic_maps_place, Color.YELLOW);
        AHBottomNavigationItem item2 = new AHBottomNavigationItem(mTiltls[1], R.mipmap.ic_maps_local_bar, Color.YELLOW);
        AHBottomNavigationItem item3 = new AHBottomNavigationItem(mTiltls[2], R.mipmap.ic_maps_local_restaurant, Color.YELLOW);
        AHBottomNavigationItem item4 = new AHBottomNavigationItem(mTiltls[3], R.mipmap.ic_book_white_24dp, Color.YELLOW);
        AHBottomNavigationItem item5 = new AHBottomNavigationItem(mTiltls[4], R.mipmap.ic_github_circle_white_24dp, Color.YELLOW);

        bottomNavigationItems.add(item1);
        bottomNavigationItems.add(item2);
        bottomNavigationItems.add(item3);
        bottomNavigationItems.add(item4);
        bottomNavigationItems.add(item5);

        bottomNavigation.addItems(bottomNavigationItems);



        //初始化消息提示
        notification=new  AHNotification.Builder()
                .setText("3")
                .setTextColor(Color.WHITE)
                .setBackgroundColor(Color.RED)
                .build();
        //为最后一个加消息提示
        bottomNavigation.setNotification(notification,4);

        //添加Viewpager中Fragment集合
        for (int i = 0; i < mTiltls.length; i++) {
            if (i != 4) {
                myFragment.add(TestFragment.getInstance(mTiltls[i].toString()));
            }else {
                myFragment.add(TestFragment.getInstance(""));
            }

        }
        //ViewPager绑定适配器
        viewPager.setAdapter(new CustomPagerAdapter(getSupportFragmentManager()));

    }
    //初始化监听
    private void initListener() {

        bottomNavigation.setOnTabSelectedListener(this);
    }


    /**  * tab 选中的效果  * @param position int: Position of the selected tab  * @param wasSelected boolean: true if the tab was already selected  * @return  */  @Override
    public boolean onTabSelected(int position, boolean wasSelected) {
        viewPager.setCurrentItem(position, false);

        if (position == 1) {
            bottomNavigation.setNotification("1", 1);

            floatingActionButton.setVisibility(View.VISIBLE);
            floatingActionButton.setAlpha(0f);
            floatingActionButton.setScaleX(0f);
            floatingActionButton.setScaleY(0f);

            floatingActionButton.animate()
                    .alpha(1)
                    .scaleX(1)
                    .scaleY(1)
                    .setDuration(300)
                    .setInterpolator(new OvershootInterpolator())
                    .setListener(new Animator.AnimatorListener() {
                        @Override
                        public void onAnimationStart(Animator animation) {

                        }

                        @Override
                        public void onAnimationEnd(Animator animation) {
                            floatingActionButton.animate()
                                    .setInterpolator(new LinearOutSlowInInterpolator())
                                    .start();
                        }

                        @Override
                        public void onAnimationCancel(Animator animation) {

                        }

                        @Override
                        public void onAnimationRepeat(Animator animation) {

                        }
                    })
                    .start();

        } else {
            if (floatingActionButton.getVisibility() == View.VISIBLE) {
                floatingActionButton.animate()
                        .alpha(0)
                        .scaleX(0)
                        .scaleY(0)
                        .setDuration(300)
                        .setInterpolator(new LinearOutSlowInInterpolator())
                        .setListener(new Animator.AnimatorListener() {
                            @Override
                            public void onAnimationStart(Animator animation) {

                            }

                            @Override
                            public void onAnimationEnd(Animator animation) {
                                floatingActionButton.setVisibility(View.GONE);
                            }

                            @Override
                            public void onAnimationCancel(Animator animation) {
                                floatingActionButton.setVisibility(View.GONE);
                            }

                            @Override
                            public void onAnimationRepeat(Animator animation) {

                            }
                        })
                        .start();
            }
        }


        return true;
    }


    //ViewPager Adapter  真正开发  记得要新建一个类,尽可能的少用内部类
    private class CustomPagerAdapter extends FragmentPagerAdapter {


        public CustomPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return myFragment == null ? null : myFragment.get(position);
        }

        @Override
        public int getCount() {

            return myFragment.size() == 0 ? 0 : myFragment.size();
        }


    }
}

代码注释已经很清楚了,不做太多重复解释。



除了上面显示的底部导航栏效果,还有一种也是较为常见的,先上图:


感兴趣可以到Github,传送门:https://github.com/armcha/Space-Navigation-View