上午记录了TabLayout的使用,简单实现了一个顶部可滑动的导航效果,突然想到Material Design的另一个控件BottomNavigationView,可以实现类似淘宝、微信、QQ、京东的底部导航栏的效果,下面就来介绍一下使用BottomNavigationView来实现底部导航栏的效果。

使用该控件同样需要添加Material Design的依赖:(运行环境是在Android Studio 3.0)

implementation 'com.android.support:design:28.0.0-alpha1'

因为BottomNavigationView控件是通过app:menu属性,使用Menu的形式为底部导航栏指定元素的,所以第一步就要新建一个菜单xml文件,在menu文件夹下新建bottom_navigation_view.xml,布局内容如下:

<?xml version="1.0" encoding="utf-8"?>                

 

 BottomNavigationView一般也是和ViewPager+Fragment搭配使用,所以第二步就写下布局文件,

activity_bottom_navigation_view.xml布局内容如下:

<?xml version="1.0" encoding="utf-8"?>                        

 创建BottonNaviFragment继承自Fragment,其布局文件fragment_bottom_navi.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>    

BottonNaviFragment.java文件如下: 

@SuppressLint("ValidFragment")public class BottonNaviFragment extends Fragment {    private TextView textView;    private String title;    public BottonNaviFragment(String title) {        this.title = title;    }    @Nullable    @Override    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View view=inflater.inflate(R.layout.fragment_bottom_navi,container,false);        textView=view.findViewById(R.id.tv_content);        return view;    }    @Override    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {        super.onViewCreated(view, savedInstanceState);        textView.setText(title);    }}

 创建Fragment适配器文件FragmentAdapter.java文件如下:

public class FragmentAdapter extends FragmentPagerAdapter {    private List list;     //存放ViewPager中要填充的Fragment    public FragmentAdapter(FragmentManager fm,List list) {        super(fm);        this.list=list;    }    @Override    public Fragment getItem(int i) {        return list.get(i);    }    @Override    public int getCount() {        return list.size();    }}

 BottomNavigationViewActivity.java文件如下:

public class BottomNavigationViewActivity extends AppCompatActivity {    private ViewPager viewPager;    private BottomNavigationView bottomNavigationView;    private MenuItem menuItem;  //菜单子项    private List list;     private FragmentAdapter fragmentAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_bottom_navigation_view);        initView();        initData();    }    private void initView() {        viewPager=findViewById(R.id.viewpager);        bottomNavigationView=findViewById(R.id.bottom_navigation_view);                //viewPager滑动监听        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {            }            @Override            public void onPageSelected(int position) {                if(menuItem!=null){                    menuItem.setChecked(false);                }else{                    bottomNavigationView.getMenu().getItem(0).setChecked(false);                }                menuItem=bottomNavigationView.getMenu().getItem(position);                menuItem.setChecked(true);            }            @Override            public void onPageScrollStateChanged(int state) {            }        });        //bottmNavigationView菜单选择监听        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {            @Override            public boolean onNavigationItemSelected(@NonNull MenuItem item) {                switch(item.getItemId()){                    case R.id.item_home:                        viewPager.setCurrentItem(0);                        break;                    case R.id.item_music:                        viewPager.setCurrentItem(1);                        break;                    case R.id.item_find:                        viewPager.setCurrentItem(2);                        break;                }                return false;            }        });    }    private void initData() {        list=new ArrayList<>();        list.add(new BottonNaviFragment("首页"));        list.add(new BottonNaviFragment("音乐"));        list.add(new BottonNaviFragment("发现"));        fragmentAdapter=new FragmentAdapter(getSupportFragmentManager(),null,list);        viewPager.setAdapter(fragmentAdapter);    }}

到此运行下项目,效果如图:

 默认元素选中时图标、文字的颜色为@color/colorPrimary,如果我们想改变导航栏中图标、文字在选中和未选中时的颜色,可以通过BottomNavigationView控件的两个属性去实现,分别是

app:itemTextColor=""app:itemIconTint=""

 为了方便效果展示,在这里我们设定图标、文字在选中时颜色为红色,未选中时为黑色,涉及到颜色选择,需要在color文件夹下新建一个颜色选择器bottomnavigation_select.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>        

 然后在activity_bottom_navigation_view.xml中的BottomNavigationView控件下,增加属性:

app:itemTextColor="@color/bottomnavigation_select"app:itemIconTint="@color/bottomnavigation_select"

运行一下,效果如图:

 

 以上是导航栏只有3个元素时效果,下面将元素增加到4个,运行效果如图:

从图中可以发现,当导航栏中元素增加到4个时,效果就不一样了,只有当元素选中以及滑动到对应元素时,文字才会出现,未选中时,文字是隐藏的。 这是因为官方的BottomNavigationView默认有个放大的ShiftingMode效果,但是尚未支持代码层级的切换。在3个元素及以下时是默认关闭的,而到了4个及以上时就会开启ShiftingMode效果,并且没有任何属性和方法去修改ShiftingMode,此时我们只能通过反射来修改:

新建一个BottomNavigationView的帮助者类BottomNavigationViewHelper.java,代码如下:

import android.support.design.internal.BottomNavigationItemView;import android.support.design.internal.BottomNavigationMenuView;import android.support.design.widget.BottomNavigationView;import android.util.Log;import java.lang.reflect.Field;/** * 新建一个BottomNavigationview帮助者类, * 通过反射来修改ShiftingMode */public class BottomNavigationViewHelper {    public static 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("BNVHelper", "Unable to get shift mode field", e);        } catch (IllegalAccessException e) {            Log.e("BNVHelper", "Unable to change value of shift mode", e);        }    }}

 然后在 BottomNavigationViewActivity.java中调用BottomNavigationViewHelper的静态方法disableShiftMode()即可。

bottomNavigationView=findViewById(R.id.bottom_navigation_view);BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

当你的build.gradle中 依赖库 'com.android.support:appcompat-v7:X.0.0-rc02' 中X小于28时,以上代码是没有问题的,当X等于28时(我使用的是Android Studio 3.0,依赖包是implementation 'com.android.support:appcompat-v7:28.0.0-rc02'),item.setShiftingMode(false)就会报Cannot resolve method 'setShiftingMode(Boolean)'的错误,借鉴了

https://stackoverflow.com/questions/51342200/cannot-resolve-method-setshiftingmodeboolean-in-bottomnavigationview的解决方式,将BottomNavigationViewHelper.java代码修改如下:

public class BottomNavigationViewHelper {    @SuppressLint("RestrictedApi")    public static void removeNavigationShiftMode(BottomNavigationView view) {        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);        menuView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);        menuView.buildMenuView();    }}

 同样的,然后在 BottomNavigationViewActivity.java中调用BottomNavigationViewHelper的静态方法removeNavigationShiftMode()

bottomNavigationView=findViewById(R.id.bottom_navigation_view);BottomNavigationViewHelper.removeNavigationShiftMode(bottomNavigationView);

 一番修改之后,再运行下项目,看下效果:

 此时,4个元素的效果和3个元素的效果就一样啦。

最后关于BottomNavigationView控件作点补充:

1、如果要设置底部导航栏的背景颜色,可以通过BottomNavigationView的属性app:itemBackground来设置,默认是当前主题的背景色,白色or黑色。

2、官方建议导航栏元素item个数为3-5个 ,最多5个,如果设置6个会直接报错。设置2个则不会报错,但是如果是2个的话不建议使用该控件。

3、如果想实现元素是不带文字的图标,可以不设置菜单的title值,例如,不设置“发现”的元素文字,运行后效果如下方:

好啦,关于BottomNavigationView实现底部导航栏的使用就介绍到这里啦。 

 

 

更多相关文章

  1. reactnative 在Android上添加阴影效果
  2. [置顶] android 自定义ListView实现元素前移后退的动画特效
  3. linearlayout总结
  4. android中selector改变界面状态用法小结
  5. Android基础教程(二)之五大布局对象
  6. Android(安卓)RecycleView实现不同样式Item样式效果完美解决
  7. [转]创建不可见的Activity
  8. 我的Android进阶之旅------>android Toast大全(五种情形)建立属于
  9. Android(安卓)之 史上最细 Material Design

随机推荐

  1. Android地图和定位学习总结
  2. TextView控件使用小技巧
  3. android 圆环倒计时控件
  4. aes文件读取
  5. 【30篇突击 android】源码统计 十四
  6. Android2.2平台上支持多camera(二)
  7. Android官方技术文档翻译——Eclilpse项
  8. android 开发 实现自动安装
  9. Android通过SystemProperties类查看系统
  10. Android JavaBinder: !!! FAILED BINDER