1.BottomNavigationVIew,它是Android Support Library 25.0.0 版本中,新增加了一个API,底部导航视图。
支持库:implementation 'com.android.support:design:28.0.0'
2.看布局文件:
<android.support.design.widget.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_navigation">
</android.support.design.widget.BottomNavigationView>
属性一: iteamBackground 指定的是底部导航栏的背景颜色,默认是主题的颜色;
属性二: iteamIconTint 指的是导航栏中图片的颜色
属性三: iteamTextColor 指的是导航栏文字的颜色
menu的布局文件:
<?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/navigation_home"
android:icon="@drawable/bottom_item_icon_tint_list"
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_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中显示不同个数的项目时,下侧显示的情况很诡异。
一、当有1,2,4个时,两端有空白。
解决办法:在BottomNavigationVIew标签下添加属性:android:background="@color/white "app:itemBackground="@color/white"
也就是item的背景要和整个的背景一致,就不会出现上面的情况了;或者不设置item的背景,只设置控件的背景。
二、当item的数量是4、5时,只用选中的条目下面会出现文字,其他的都被隐藏了。而小于等于三个时,显示正常。
解决办法:在BottomNavigationVIew标签下添加属性:app:labelVisibilityMode="labeled"
这里有四个属性值:auto和selected效果差不多,都是上面的选中了显示,不选中的隐藏。
labeled: unlabeled:
所以我们选labeled即可。
3.activity代码:
package com.ysl.mymaterialdesign.activity;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.BottomNavigationView.OnNavigationItemSelectedListener;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import com.ysl.mymaterialdesign.R;
import com.ysl.mymaterialdesign.fragment.DashboardFragment;
import com.ysl.mymaterialdesign.fragment.HomeFragment;
import com.ysl.mymaterialdesign.fragment.NotificationFragment;
import com.ysl.mymaterialdesign.fragment.PersonalFragment;
public class MainActivity extends AppCompatActivity {
protected Fragment currentFragment;
private HomeFragment homeFragment;
private DashboardFragment dashboardFragment;
private NotificationFragment notificationFragment;
private PersonalFragment personalFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView bottom_navigation = findViewById(R.id.bottom_navigation);
bottom_navigation.setOnNavigationItemSelectedListener(navigationItemSelectedListener);
initData();
}
private BottomNavigationView.OnNavigationItemSelectedListener navigationItemSelectedListener = new OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.navigation_home:
clickHomeItem();
return true;
case R.id.navigation_dashboard:
clickDashboardItem();
return true;
case R.id.navigation_notifications:
clickNotificationItem();
return true;
case R.id.navigation_person:
clickPersonalItem();
return true;
}
return false;
}
};
private void initData() {
if (homeFragment == null) {
homeFragment = HomeFragment.newInstance("","");
}
if (!homeFragment.isAdded()) {
getSupportFragmentManager().beginTransaction().add(R.id.fl_content, homeFragment).commitAllowingStateLoss();
} else {
getSupportFragmentManager().beginTransaction().show(homeFragment).commitAllowingStateLoss();
}
currentFragment = homeFragment;
}
protected void addOrShowFragment(FragmentTransaction transaction, Fragment fragment) {
if (currentFragment == fragment){
return;
}
if (!fragment.isAdded()) { // 如果当前fragment未被添加,则添加到Fragment管理器中
transaction.hide(currentFragment).add(R.id.fl_content, fragment).commitAllowingStateLoss();
} else {
transaction.hide(currentFragment).show(fragment).commitAllowingStateLoss();
}
currentFragment = fragment;
}
private void clickHomeItem() {
if (homeFragment == null) {
homeFragment = HomeFragment.newInstance("","");
}
addOrShowFragment(getSupportFragmentManager().beginTransaction(), homeFragment);
}
private void clickDashboardItem() {
if (dashboardFragment == null) {
dashboardFragment = DashboardFragment.newInstance("","");
}
addOrShowFragment(getSupportFragmentManager().beginTransaction(), dashboardFragment);
}
private void clickNotificationItem() {
if (notificationFragment == null) {
notificationFragment = NotificationFragment.newInstance("","");
}
addOrShowFragment(getSupportFragmentManager().beginTransaction(), notificationFragment);
}
private void clickPersonalItem() {
if (personalFragment == null) {
personalFragment = PersonalFragment.newInstance("","");
}
addOrShowFragment(getSupportFragmentManager().beginTransaction(), personalFragment);
}
}
关键的一步就是:
4.怎么替换为自己项目设计的底部图标和字体的颜色:
在BottomNavigationVIew标签下添加属性:iteamIconTint iteamTextColor
color_state_menu_navi 是一个颜色选择器
res/color/color_state_menu_navi.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/green"/>
<item android:state_checked="false" android:color="@color/gray"/>
</selector>
选中的为绿色,未选中的为灰色。
5.上面使用的图标都是系统自带的,我们怎么替换为自己想要的图标
在menu的xml文件中:
<item
android:id="@+id/navigation_home"
android:icon="@drawable/bottom_item_icon_tint_list"
android:title="@string/title_home" />
把icon替换为自己想要的图标即可,bottom_item_icon_tint_list为一个图片选择器:
<?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/news2"/>
<item android:drawable="@drawable/news1"/>
</selector>
图片自己找两张即可。
看一下效果:
图标确实替换成功了,选择器也好用着呢,但颜色好像不对,我们放进去的是蓝色,可为什么变成绿色了呢???
这是由于属性 app:itemIconTint="@color/color_state_menu_navi" 导致的,还记得前面用的选中是绿色,未选中是灰色。
解决:在activity中:
也就是把此属性设置为null。即可
6.动画
可以看到点击item时,都有动画。而且下面的字会变大,这就是动画产生的原因。个人觉得挺好看的。但如果项目中设计的是没有动画,改怎么去掉呢:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!--BottomNavigationView 的选中没有选中的字体大小设置一致-->
<dimen name="design_bottom_navigation_active_text_size">14dp</dimen>
<dimen name="design_bottom_navigation_text_size">14dp</dimen>
<!--BottomNavigationView 文字和图标的距离-->
<dimen name="design_bottom_navigation_margin">1dp</dimen>
<!--BottomNavigationView 整体高度-->
<dimen tools:override="true" name="design_bottom_navigation_height">56dp</dimen>
</resources>
代码中有详细的描述,只要两次字体大小一致,就不会产生动画了。而且文本和图标的距离也可以自行设置。导航栏的高度也可以设置。上面这些dimen设置,注释掉就是原始的效果了,打开就是想要设置的效果了,Java代码一句也不用写。
7.BottomNavigationVIew + Fragment搭建简单的框架
主要就是在 BottomNavigationView.OnNavigationItemSelectedListener 监听器中填充不同的fragment。
代码在上面的3里面。
看一下效果:
最后贴一下布局的代码:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:labelVisibilityMode="labeled"
app:itemIconTint="@color/color_state_menu_navi"
app:itemTextColor="@color/color_state_menu_navi"
app:menu="@menu/bottom_navigation">
<!--android:background="@color/white"-->
<!--app:itemBackground="@color/gray"-->
</com.google.android.material.bottomnavigation.BottomNavigationView>