BottomNavigationView 的使用
drawable文件夹下建立nav_change.xml ,并在布局中引用
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="@color/color_checked"></item>
<item android:color="@color/color_unchecked"></item>
</selector>
布局中设置
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:orientation="vertical"
android:layout_height="match_parent"
tools:context="com.example.yanruifeng.myapplication.TestBottonNavigationActivity">
<android.support.design.widget.BottomNavigationView
android:id="@+id/bnv_nav"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
app:menu="@menu/navigation"
app:itemTextColor="@drawable/nav_change"
app:itemIconTint="@drawable/nav_change"
app:itemBackground="@color/color_bg"
android:layout_height="96px"></android.support.design.widget.BottomNavigationView>
</RelativeLayout>
在Activity中的使用
public class TestBottonNavigationActivity extends AppCompatActivity {
@BindView(R.id.bnv_nav)
BottomNavigationView bottomNavigationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_botton_navigation);
ButterKnife.bind(this);
bottomNavigationView.getMenu().findItem(R.id.ic_home).setIcon(R.drawable.home_selected);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
resetIconColor();
switch (item.getItemId()){
case R.id.msg:
item.setIcon(R.drawable.msg_selected);
break;
case R.id.me:
item.setIcon(R.drawable.my_selected);
break;
case R.id.ic_home:
item.setIcon(R.drawable.home_selected);
break;
}
return true;
}
});
}
public void resetIconColor(){
bottomNavigationView.getMenu().findItem(R.id.ic_home).setIcon(R.drawable.home);
bottomNavigationView.getMenu().findItem(R.id.msg).setIcon(R.drawable.msg);
bottomNavigationView.getMenu().findItem(R.id.me).setIcon(R.drawable.my);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
实际上不在Activity中动态更改图标也可以,在res/menu/navigation.xml中让icon引入drawable下的xml
<?xml version="1.0" encoding="utf-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/ic_home"
android:icon="@drawable/nav_homeicon_change"
android:title="首页" />
<item
android:id="@+id/msg"
android:icon="@drawable/nav_msgicon_change"
android:title="消息" />
<item
android:id="@+id/me"
android:icon="@drawable/nav_myicon_change"
android:title="我的"/>
</menu>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/home_selected"></item>
<item android:state_checked="false" android:drawable="@drawable/home"></item>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/msg_selected"></item>
<item android:state_checked="false" android:drawable="@drawable/msg"></item>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/my_selected"></item>
<item android:state_checked="false" android:drawable="@drawable/my"></item>
</selector>
遇到的坑
-
问题一:使用的时候 item 数大于 3 个时会有位移
使用下面的类通过反射来修改
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); } } }
使用:
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation); BottomNavigationViewHelper.disableShiftMode(navigation);
-
问题二:
要实现上面的这样的效果:
-
我们把 app:menu=”@menu/navigation” 指向的 navigation 修改为
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/navigation_home" android:icon="@drawable/ic_home_black_24dp" android:title="@string/title_home" /> <item android:id="@+id/navigation_dashboard" android:icon="@drawable/ic_dashboard_black_24dp" android:title="@string/title_dashboard" /> <item android:id="@+id/navigation_center" android:icon="@null" android:title="" /> <item android:id="@+id/navigation_notifications" android:icon="@drawable/ic_notifications_black_24dp" android:title="@string/title_notifications" /> <item android:id="@+id/navigation_person" android:icon="@drawable/ic_person_black_24dp" android:title="@string/title_person" /> </menu>
即中间第三个 menu 不给设置图片和文字
-
然后我们修改布局文件(即用一个LinearLayout (只是正中间有一个Image), 覆盖在 BottomNavigation 之上)
如果中间的按钮需要的是替换当前页面的fragment的话我们那么我们的 image 只用作显示使用,如果需要按钮的功能是打开一个新页面,那么我们需要给这个 imageVIew 设置一个点击事件,这样 BottomNavigation 就不会拿到点击事件,把中间的 item 标记为选中
<FrameLayout android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:clipToPadding="true"> <android.support.design.widget.BottomNavigationView android:id="@+id/navigation" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_gravity="bottom" android:background="?android:attr/windowBackground" app:menu="@menu/navigation" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:elevation="16dp"> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" /> <ImageView android:id="@+id/navigation_center_image" android:layout_width="0dp" android:layout_height="match_parent" android:layout_gravity="center" android:layout_weight="1" android:padding="5dp" android:src="@mipmap/ic_launcher" /> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" /> </LinearLayout> </FrameLayout>
-
-
问题三:选中 item 时 item 的文本会有一个动画,那么如何取消动画。icon 也会上移一点。
design_bottom_navigation_active_text_size
design_bottom_navigation_text_size
上面的参数是item选中没有选中的文本大小,我们把它设置成一样的话就没有动画了
design_bottom_navigation_margin
是图标的 margin bottom 的值我们可以调整他让 icon 垂直居中
<!--http://www.jianshu.com/p/7b2d842267ab--> <!--BottomNavigationView 的选中没有选中的字体大小--> <dimen name="design_bottom_navigation_active_text_size">10sp</dimen> <dimen name="design_bottom_navigation_text_size">10sp</dimen> <!--BottomNavigationView 只放图标时的设置--> <dimen name="design_bottom_navigation_active_text_size">0sp</dimen> <dimen name="design_bottom_navigation_text_size">0sp</dimen> <dimen name="design_bottom_navigation_margin">16dp</dimen>
把上面的 根据需要 copy 到 res/values/dimens 中就行