Android Design Library之二: BottomNavigationView
来源:互联网 发布:北京java开发工程师 编辑:程序博客网 时间:2024/05/21 22:55
BottomNavitagionView
出现之前,我们首先底部的导航栏大多是使用RadioGroup
+RadioButton
的特性来实现。现在官方为我们提供了另外的一条路。先来尝试下。
Demo
打开官方文档里面就有示例程序,比着敲一遍,看下效果。
<android.support.design.widget.BottomNavigationView android:layout_width="match_parent" android:layout_height="55dp" android:layout_alignParentBottom="true" android:layout_gravity="center" android:gravity="center" app:itemIconTint="#009877" app:itemTextColor="#009877" app:paddingStart="10dp" app:paddingEnd="10dp" app:itemBackground="@color/white" app:menu="@menu/bottom_nav"/>
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_nav_android" android:icon="@drawable/ic_android_black_36dp" app:showAsAction="ifRoom" android:title="Android"/> <item android:id="@+id/menu_nav_lock" android:icon="@drawable/ic_lock_black_36dp" app:showAsAction="ifRoom" android:title="Lock"/> <item android:id="@+id/menu_nav_group_work" android:icon="@drawable/ic_group_work_black_36dp" app:showAsAction="ifRoom" android:title="Work"/></menu>
效果如下
嗯。效果还是不错的。但是有时候我们需要的是颜色的变化,这个时候我们需要一个color
。在res
下的color
文件夹下创建一个文件名为bottom_nav
的文件内容如下。
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/nav_checked" android:state_checked="true"/> <item android:color="@color/nav_unchecked" android:state_checked="false"/></selector>
之后为BottomNavitagionView
设置上就可以了。
效果如下
app:itemIconTint="@color/bottom_nav" app:itemTextColor="@color/bottom_nav"
问题
真的就这么就完了么? too young,too simple。我们底部的菜单项肯定不一定是3个。如果是4个。我们试一下,再加菜单项。很简单为menu
再添加个item
。来看下效果:
WTF
来看下源码看看到底发生了什么?BottomNavigationView
的源码
private final MenuBuilder mMenu; private final BottomNavigationMenuView mMenuView; private final BottomNavigationPresenter mPresenter = new BottomNavigationPresenter(); private MenuInflater mMenuInflater; //.....省略代码 public void inflateMenu(int resId) { mPresenter.setUpdateSuspended(true); getMenuInflater().inflate(resId, mMenu); mPresenter.setUpdateSuspended(false); mPresenter.updateMenuView(true); }
我们看到。其中主要有这几个属性,通过查看代码我们可以看到。BottomNavigationPresenter
来连接Menu
和BottomNavigationMenuView
的。BottomNavigationPresenter
的部分代码
private MenuBuilder mMenu; private BottomNavigationMenuView mMenuView; @Override public void initForMenu(Context context, MenuBuilder menu) { mMenuView.initialize(mMenu); mMenu = menu; } ....省略... @Override public void updateMenuView(boolean cleared) { if (mUpdateSuspended) return; if (cleared) { mMenuView.buildMenuView(); } else { mMenuView.updateMenuView(); } }
我们可以看到。更新MenuView
的方法是通过Presenter
来调用的。其内部的代码
public void buildMenuView() { mShiftingMode = mMenu.size() > 3; for (int i = 0; i < mMenu.size(); i++) { mPresenter.setUpdateSuspended(true); mMenu.getItem(i).setCheckable(true); mPresenter.setUpdateSuspended(false); BottomNavigationItemView child = getNewItem(); mButtons[i] = child; child.setIconTintList(mItemIconTint); child.setTextColor(mItemTextColor); child.setItemBackground(mItemBackgroundRes); child.setShiftingMode(mShiftingMode); child.initialize((MenuItemImpl) mMenu.getItem(i), 0); child.setItemPosition(i); child.setOnClickListener(mOnClickListener); addView(child); } mActiveButton = Math.min(mMenu.size() - 1, mActiveButton); mMenu.getItem(mActiveButton).setChecked(true); }
这里我们应该就看出来端倪了。mShiftingMode
是个boolean
值,当menu
的长度大于三时,就为true
。也就为每一个BottomNavigationItemView
设置上了child.setShiftingMode(mShiftingMode);
true。在这里每一个BottomNavigationItemView
就是一个tab
。
在BottomNavigationItemView
的代码中我们可以看到。其填充的布局为R.layout.design_bottom_navigation_item
布局中有两个TextView
(smallLabel和largeLabel) 和一个ImageView
(icon),详细的代码自己搜一下吧。在design
包中,这里就不贴出来了。
if (mShiftingMode) { if (checked) { LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams(); iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; iconParams.topMargin = mDefaultMargin; mIcon.setLayoutParams(iconParams); mLargeLabel.setVisibility(VISIBLE); ViewCompat.setScaleX(mLargeLabel, 1f); ViewCompat.setScaleY(mLargeLabel, 1f); } else { LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams(); iconParams.gravity = Gravity.CENTER; iconParams.topMargin = mDefaultMargin; mIcon.setLayoutParams(iconParams); mLargeLabel.setVisibility(INVISIBLE); ViewCompat.setScaleX(mLargeLabel, 0.5f); ViewCompat.setScaleY(mLargeLabel, 0.5f); } mSmallLabel.setVisibility(INVISIBLE); } else { if (checked) { LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams(); iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; iconParams.topMargin = mDefaultMargin + mShiftAmount; mIcon.setLayoutParams(iconParams); mLargeLabel.setVisibility(VISIBLE); mSmallLabel.setVisibility(INVISIBLE); ViewCompat.setScaleX(mLargeLabel, 1f); ViewCompat.setScaleY(mLargeLabel, 1f); ViewCompat.setScaleX(mSmallLabel, mScaleUpFactor); ViewCompat.setScaleY(mSmallLabel, mScaleUpFactor); } else { LayoutParams iconParams = (LayoutParams) mIcon.getLayoutParams(); iconParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; iconParams.topMargin = mDefaultMargin; mIcon.setLayoutParams(iconParams); mLargeLabel.setVisibility(INVISIBLE); mSmallLabel.setVisibility(VISIBLE); ViewCompat.setScaleX(mLargeLabel, mScaleDownFactor); ViewCompat.setScaleY(mLargeLabel, mScaleDownFactor); ViewCompat.setScaleX(mSmallLabel, 1f); ViewCompat.setScaleY(mSmallLabel, 1f); } }
啊哈。看了这么多终于找到原因了。 这就是问题所在。我们见到如果我们吧mShiftingMode
设置为false
那么就不会出现那种效果。怎么设置呢。我们可以使用反射的机制来进行设置。
代码如下
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); item.setShiftingMode(false); item.setChecked(item.getItemData().isChecked()); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
http://blog.magicer.xyz/2017/06/android-design-library-bottomnavigationview/
- Android Design Library之二: BottomNavigationView
- Android Material Design 之 BottomNavigationView
- Android 之 Material Design(二)—BottomNavigationView
- Design: Android Design Support Library (二)
- Android开发 之 BottomNavigationView
- Android design library(二)----------FloatingActionButton + Snackbar
- Android Design Support Library使用详解(二)
- Android Design Support Library之TabLayout
- Android Design Support Library之CoordinatorLayout,AppBarLayout
- 深度剖析之 Material Design Android Library
- Android Support Design Library之CoordinatorLayout
- Android Support Design Library之NavigationView
- Android Support Design Library之FloatingActionButton
- Android Support Design Library之TabLayout
- Android Support Design Library之TextInputLayout
- Android Support Design Library之NavigationView
- Android Design Support Library实践之Snackbar
- Android Design Support Library之TabLayout
- NOIP2017多校联测&提高组模拟21 11.3
- 一篇文章讲清楚人工智能、机器学习和深度学习的区别与联系
- spark 和 hadoop的web UI
- nginx缓存静态文件
- 原生 JS 写的手机端上下拉
- Android Design Library之二: BottomNavigationView
- 何时赋值问题
- cocos2dx_lua 触摸监听
- Android Binder之应用层精彩解析
- Easy UI DataGrid获取指定行指定列的数据
- Java中常见数据结构:list与map -底层如何实现
- MyBatis mapper文件中的变量引用方式#{}与${}的差别
- 关于BigDecimal 除法的java.lang.ArithmeticException问题
- linux下安装使用libuuid(uuid-generate)