简介:Google推出的BottomNavigationBar底部导航栏
版本更新:2019-5-13
补充布局文件activity_main
1、默认使用studio背景图,防止少图片资源(效果图虽不尽人意~)
2、项目build.gradle添加依赖:(注意studio3.0以下将implementation 换成 compile)
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.4'
3、MainActivity
import android.graphics.Color;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.ashokvarma.bottomnavigation.BottomNavigationBar;
import com.ashokvarma.bottomnavigation.BottomNavigationItem;
import com.ashokvarma.bottomnavigation.ShapeBadgeItem;
import com.ashokvarma.bottomnavigation.TextBadgeItem;
import java.lang.reflect.Field;
public class MainActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener {
private FragmentManager mFragmentManager;
private BottomNavigationBar bottomNavigationBar;
private FirstFragment firstFragment;
private SecondFragment secondFragment;
private ThirdFragment thirdFragment;
private FourthFragment fourthFragment;
//默认选择第一个fragment
private int lastSelectedPosition = 0;
private FragmentTransaction transaction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNavigationBar = this.findViewById(R.id.bottomNavigationBar);
showNumberAndShape();
initNavigation();
}
/**
* 初始底部导航栏
*/
private void initNavigation() {
//导航栏Item的个数<=3 用 MODE_FIXED 模式,否则用 MODE_SHIFTING 模式
bottomNavigationBar.setMode(BottomNavigationBar.MODE_FIXED);
bottomNavigationBar.setTabSelectedListener(this);//监听切换点击事件
//bottomNavigationBar.setBarBackgroundColor("#595757");//背景颜色
//1、BACKGROUND_STYLE_DEFAULT:如果设置的Mode为MODE_FIXED,将使用BACKGROUND_STYLE_STATIC 。如果Mode为MODE_SHIFTING将使用BACKGROUND_STYLE_RIPPLE。
//2、BACKGROUND_STYLE_STATIC:点击无水波纹效果
//3、BACKGROUND_STYLE_RIPPLE:点击有水波纹效果
bottomNavigationBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_STATIC);
//需要添加的item数
bottomNavigationBar
//选中时的图片的资源、文字
.addItem(new BottomNavigationItem(R.drawable.home, "首页")
//选中的颜色
.setActiveColor(R.color.colorAccent)
//选中的颜色(资源文件 下面同上)
//.setActiveColorResource(R.color.colorAccent)
//未选中的颜色(默认灰色 可注释)
.setInActiveColor("#999999")
//未选中时的图片的资源
.setInactiveIconResource(R.drawable.ic_launcher_background))
.addItem(new BottomNavigationItem(R.drawable.home, "订单")
.setActiveColorResource(R.color.colorAccent)
.setInActiveColor("#999999")
.setInactiveIconResource(R.drawable.ic_launcher_background)).
addItem(new BottomNavigationItem(R.drawable.ic_launcher_background, "购物车")
.setActiveColorResource(R.color.colorAccent)
.setInActiveColor("#999999")
.setBadgeItem(textBadgeItem)
.setInactiveIconResource(R.drawable.ic_launcher_background)).
addItem(new BottomNavigationItem(R.drawable.ic_launcher_background, "我的")
.setActiveColorResource(R.color.colorAccent)
.setInActiveColor("#999999")
.setBadgeItem(shapeBadgeItem)
.setInactiveIconResource(R.drawable.ic_launcher_background))
.setFirstSelectedPosition(lastSelectedPosition)//设置默认选中项
//.setFab(FloatingActionButton的id)//FloatingActionButton 关联
.initialise();//注意此句放在最后
setIconItemMargin(bottomNavigationBar,10,25,14);
setDefaultFragment();
}
/**
* 设置默认开启的fragment
*/
private void setDefaultFragment() {
mFragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = mFragmentManager.beginTransaction();
firstFragment = new FirstFragment();
transaction.add(R.id.tb, firstFragment);
transaction.commit();
}
/**
* 切换事件
*/
@Override
public void onTabSelected(int position) {
lastSelectedPosition = position;//每次点击赋值
//开启事务
transaction = mFragmentManager.beginTransaction();
hideFragment(transaction);
switch (position) {
case 0:
if (firstFragment == null) {
firstFragment = new FirstFragment();
transaction.add(R.id.tb, firstFragment);
} else {
transaction.show(firstFragment);
}
// transaction.replace(R.id.tb, firstFragment);
break;
case 1:
if (secondFragment == null) {
secondFragment = new SecondFragment();
transaction.add(R.id.tb, secondFragment);
} else {
transaction.show(secondFragment);
}
break;
case 2:
if (thirdFragment == null) {
thirdFragment = new ThirdFragment();
transaction.add(R.id.tb, thirdFragment);
} else {
transaction.show(thirdFragment);
}
break;
case 3:
if (fourthFragment == null) {
fourthFragment = new FourthFragment();
transaction.add(R.id.tb, fourthFragment);
} else {
transaction.show(fourthFragment);
}
break;
}
// 事务提交
transaction.commit();
}
/**
* 隐藏当前fragment
*
* @param transaction
*/
private void hideFragment(FragmentTransaction transaction) {
if (firstFragment != null) {
transaction.hide(firstFragment);
}
if (secondFragment != null) {
transaction.hide(secondFragment);
}
if (thirdFragment != null) {
transaction.hide(thirdFragment);
}
if (fourthFragment != null) {
transaction.hide(fourthFragment);
}
}
private TextBadgeItem textBadgeItem;
private ShapeBadgeItem shapeBadgeItem;
/**
* 展示消息点
*/
private void showNumberAndShape() {
//消息
textBadgeItem = new TextBadgeItem()
.setText("99")//显示的文本
.setTextColor("#ffffff")//文本颜色
//.setTextColorResource(R.color.colorAccent)//文本颜色(资源文件-下面如同)
.setBorderWidth(6)//圆环宽度
.setBorderColor(Color.parseColor("#000000"))//圆环燕色
//.setBorderColorResource(R.color.colorPrimary)
.setBackgroundColor("#FF4081")//背景颜色
.setHideOnSelect(false);//选中是否隐藏
//.setBackgroundColorResource(R.color.colorAccent)//背景颜色
//.setAnimationDuration(300)//隐藏与动画的过渡时间(setHideOnSelect 为true时生效)
//.setGravity(Gravity.RIGHT | Gravity.TOP); //位置,默认右上角(可不设置)
//形状
shapeBadgeItem = new ShapeBadgeItem()
//也可设置为常量 (0-6之间)
.setShape(ShapeBadgeItem.SHAPE_HEART) //形状
.setShapeColor(Color.RED) //颜色
//.setShapeColorResource(R.color.colorPrimaryDark) //(同上)
.setEdgeMarginInDp(this, 0) //距离Item的边距,dp值
//.setEdgeMarginInPixels(20) //距离Item的边距,px
.setSizeInDp(this, 15, 15) //宽高值,dp
//.setSizeInPixels(30, 30) //宽高值,px
.setAnimationDuration(300) //隐藏和展示的动画速度,单位毫秒,和setHideOnSelect一起使用
//.setGravity(Gravity.LEFT) //位置,默认右上角
.setHideOnSelect(false); //true:当选中状态时消失,非选中状态显示,moren false
}
@Override
public void onTabUnselected(int position) {
}
@Override
public void onTabReselected(int position) {
}
/**
* 修改间距及图片文字大小
* @param bottomNavigationBar
* @param space 文字与图片的间距
* @param imgLen 单位:dp,图片大小
* @param textSize 单位:dp,文字大小
*/
private void setIconItemMargin(BottomNavigationBar bottomNavigationBar, int space, int imgLen, int textSize){
Class barClass = bottomNavigationBar.getClass();
Field[] fields = barClass.getDeclaredFields();
for(int i = 0; i < fields.length; i++){
Field field = fields[i];
field.setAccessible(true);
if(field.getName().equals("mTabContainer")){
try{
//反射得到 mTabContainer
LinearLayout mTabContainer = (LinearLayout) field.get(bottomNavigationBar);
for(int j = 0; j < mTabContainer.getChildCount(); j++){
//获取到容器内的各个Tab
View view = mTabContainer.getChildAt(j);
//获取到Tab内的各个显示控件
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dip2px(56));
FrameLayout container = (FrameLayout) view.findViewById(R.id.fixed_bottom_navigation_container);
container.setLayoutParams(params);
container.setPadding(dip2px(12), dip2px(0), dip2px(12), dip2px(0));
//获取到Tab内的文字控件
TextView labelView = (TextView) view.findViewById(com.ashokvarma.bottomnavigation.R.id.fixed_bottom_navigation_title);
//计算文字的高度DP值并设置,setTextSize为设置文字正方形的对角线长度,所以:文字高度(总内容高度减去间距和图片高度)*根号2即为对角线长度,此处用DP值,设置该值即可。
labelView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize);
labelView.setIncludeFontPadding(false);
labelView.setPadding(0,0,0,dip2px(20-textSize - space/2));
//获取到Tab内的图像控件
ImageView iconView = (ImageView) view.findViewById(com.ashokvarma.bottomnavigation.R.id.fixed_bottom_navigation_icon);
//设置图片参数,其中,MethodUtils.dip2px():换算dp值
params = new FrameLayout.LayoutParams(dip2px(imgLen), dip2px(imgLen));
params.setMargins(0,0,0,space/2);
params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
iconView.setLayoutParams(params);
}
} catch (IllegalAccessException e){
e.printStackTrace();
}
}
}
}
private int dip2px(float dpValue) {
final float scale = getApplication().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
其中有4个碎片在这只贴出FirstFragment (其余几乎一致)
4、FirstFragment
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FirstFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_first_fragment, container, false);
return view;
}
}
注意引用V4的包
其布局:activity_first_fragment
5、若要使用replace的显示方式,将onTabSelected监听处改为如下代码即可
1、switch处
switch (position) {
case 0:
firstFragment = new FirstFragment();
transaction.replace(R.id.tb, firstFragment);
break;
case 1:
secondFragment = new SecondFragment();
transaction.replace(R.id.tb, secondFragment);
break;
case 2:
thirdFragment = new ThirdFragment();
transaction.replace(R.id.tb, thirdFragment);
break;
case 3:
fourthFragment = new FourthFragment();
transaction.replace(R.id.tb, fourthFragment);
break;
}
2、注释 //hideFragment(transaction);这个方法
6、最后贴出TextBadgeItem和ShapeBadgeItem的属性图