在绝大多数的应用程序中,都会有底部导航栏,或者顶部导航栏,今天要介绍的就是谷歌推出的一个控件BottomNavigationView,
BottomNavigationView是android5.0以后引进的新控件
很多人可能都已经在项目中用到了,这里只给大家做一些简单的介绍以及在用的过程中遇到的一些问题
首先创建BottomNavigationView控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.yc.androidarchitecture.MainActivity">
<FrameLayout
android:id="@+id/fl_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:menu="@menu/navigation" />
</LinearLayout>
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bottom_view"
//自定义选中按钮的图标和字体的颜色
app:itemIconTint="@color/bottom_button_textcolor"
app:itemTextColor="@color/bottom_button_textcolor"
app:menu="@menu/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_notifications"
android:icon="@drawable/ic_notifications_black_24dp"
android:title="@string/title_notifications" />
</menu>
在activity中定义点击按钮的监听
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
//这里在点击按钮的时候设置相对应的fragment是否显示活着隐藏
showFragment(0);
return true;
case R.id.navigation_notifications:
showFragment(1);
return true;
}
return false;
}
};
在界面初始化的时候注册监听
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
设置选中的按钮
mNavigation.getMenu().getItem(position).setChecked(true);
这里如果用系统自带的效果的话 图标和字体自带动画效果,有些时候我们为了与ios保持一致并不想要这个效果,就需要将字体设置成点击前和点击后一致的大小即可
1.将底部导航的字体设置成一致
<dimen name="design_bottom_navigation_text_size" tools:override="true">12sp</dimen>
<dimen name="design_bottom_navigation_active_text_size" tools:override="true">12sp</dimen>
design_bottom_navigation_margin
是图标的 margin bottom 的值我们可以调整他让 icon 垂直居中
<!--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 中就行
2.xml文件
首先在res/color文件下创建一个selector文件navigation_menu_item_color.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/colorAccent"></item> <!-- selected颜色 -->
- <item android:state_pressed="true"
- android:color="@color/colorAccent"/> <!-- pressed颜色 -->
- <item android:state_focused="true"
- android:color="@color/colorAccent"/> <!-- focused颜色 -->
- <item android:color="#FFFFFF"/> <!-- default颜色 -->
- </selector>
对应填充自己的颜色就可以了。
3.java代码
上面的做完后需要在Java代码中区设置。
- /**设置MenuItem的字体颜色**/
- NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
- navigationView.setNavigationItemSelectedListener(this);
- Resources resource=(Resources)getBaseContext().getResources();
- ColorStateList csl=(ColorStateList)resource.getColorStateList(R.color.navigation_menu_item_color);
- navigationView.setItemTextColor(csl);
- /**设置MenuItem默认选中项**/
- navigationView.getMenu().getItem(0).setChecked(true);
//或者用 // mNavigation.setSelectedItemId(mNavigation.getMenu().getItem(0).getItemId());
如果以上还没达到你想要的效果那么只有自定义一个了,从网上找了一个自定义工具类 ,大概的逻辑就是动态的去设置图片文字等 , 直接上代码了
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
@SuppressLint("RestrictedApi")
public class CustomBottomNavigationView extends BottomNavigationView {
// used for animation
private int mShiftAmount;
private float mScaleUpFactor;
private float mScaleDownFactor;
private boolean animationRecord;
private float mLargeLabelSize;
private float mSmallLabelSize;
private boolean visibilityTextSizeRecord;
private boolean visibilityHeightRecord;
private int mItemHeight;
// used for setupWithViewPager
private ViewPager mViewPager;
private MyOnNavigationItemSelectedListener mMyOnNavigationItemSelectedListener;
private BottomNavigationViewExOnPageChangeListener mPageChangeListener;
private BottomNavigationMenuView mMenuView;
private BottomNavigationItemView[] mButtons;
// used for setupWithViewPager end
public CustomBottomNavigationView(Context context) {
super(context);
}
public CustomBottomNavigationView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomBottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* change the visibility of icon
*
* @param visibility
*/
public void setIconVisibility(boolean visibility) {
// 1. get mMenuView
final BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. get mIcon in mButtons
for (BottomNavigationItemView button : mButtons) {
ImageView mIcon = getField(button.getClass(), button, "mIcon");
// 4. set mIcon visibility gone
mIcon.setVisibility(visibility ? View.VISIBLE : View.INVISIBLE);
}
// 5. change mItemHeight to only text size in mMenuView
if (!visibility) {
// if not record mItemHeight
if (!visibilityHeightRecord) {
visibilityHeightRecord = true;
mItemHeight = getItemHeight();
}
// change mItemHeight
BottomNavigationItemView button = mButtons[0];
if (null != button) {
final ImageView mIcon = getField(button.getClass(), button, "mIcon");
if (null != mIcon) {
mIcon.post(new Runnable() {
@Override
public void run() {
setItemHeight(mItemHeight - mIcon.getMeasuredHeight());
}
});
}
}
} else {
// if not record the mItemHeight, we need do nothing.
if (!visibilityHeightRecord)
return;
// restore it
setItemHeight(mItemHeight);
}
mMenuView.updateMenuView();
}
/**
* change the visibility of text
*
* @param visibility
*/
public void setTextVisibility(boolean visibility) {
// 1. get mMenuView
BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. change field mShiftingMode value in mButtons
for (BottomNavigationItemView button : mButtons) {
TextView mLargeLabel = getField(button.getClass(), button, "mLargeLabel");
TextView mSmallLabel = getField(button.getClass(), button, "mSmallLabel");
if (!visibility) {
// if not record the font size, record it
if (!visibilityTextSizeRecord && !animationRecord) {
visibilityTextSizeRecord = true;
mLargeLabelSize = mLargeLabel.getTextSize();
mSmallLabelSize = mSmallLabel.getTextSize();
}
// if not visitable, set font size to 0
mLargeLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, 0);
mSmallLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, 0);
} else {
// if not record the font size, we need do nothing.
if (!visibilityTextSizeRecord)
break;
// restore it
mLargeLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, mLargeLabelSize);
mSmallLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSmallLabelSize);
}
}
// 4 change mItemHeight to only icon size in mMenuView
if (!visibility) {
// if not record mItemHeight
if (!visibilityHeightRecord) {
visibilityHeightRecord = true;
mItemHeight = getItemHeight();
}
// change mItemHeight to only icon size in mMenuView
// private final int mItemHeight;
// change mItemHeight
setItemHeight(mItemHeight - getFontHeight(mSmallLabelSize));
} else {
// if not record the mItemHeight, we need do nothing.
if (!visibilityHeightRecord)
return;
// restore mItemHeight
setItemHeight(mItemHeight);
}
mMenuView.updateMenuView();
}
/**
* get text height by font size
*
* @param fontSize
* @return
*/
private static int getFontHeight(float fontSize) {
Paint paint = new Paint();
paint.setTextSize(fontSize);
Paint.FontMetrics fm = paint.getFontMetrics();
return (int) Math.ceil(fm.descent - fm.top) + 2;
}
/**
* enable or disable click item animation(text scale and icon move animation in no item shifting mode)
*
* @param enable It means the text won't scale and icon won't move when active it in no item shifting mode if false.
*/
public void enableAnimation(boolean enable) {
// 1. get mMenuView
BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. change field mShiftingMode value in mButtons
for (BottomNavigationItemView button : mButtons) {
TextView mLargeLabel = getField(button.getClass(), button, "mLargeLabel");
TextView mSmallLabel = getField(button.getClass(), button, "mSmallLabel");
// if disable animation, need animationRecord the source value
if (!enable) {
if (!animationRecord) {
animationRecord = true;
mShiftAmount = getField(button.getClass(), button, "mShiftAmount");
mScaleUpFactor = getField(button.getClass(), button, "mScaleUpFactor");
mScaleDownFactor = getField(button.getClass(), button, "mScaleDownFactor");
mLargeLabelSize = mLargeLabel.getTextSize();
mSmallLabelSize = mSmallLabel.getTextSize();
}
// disable
setField(button.getClass(), button, "mShiftAmount", 0);
setField(button.getClass(), button, "mScaleUpFactor", 1);
setField(button.getClass(), button, "mScaleDownFactor", 1);
// let the mLargeLabel font size equal to mSmallLabel
mLargeLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSmallLabelSize);
} else {
// haven't change the value. It means it was the first call this method. So nothing need to do.
if (!animationRecord)
return;
// enable animation
setField(button.getClass(), button, "mShiftAmount", mShiftAmount);
setField(button.getClass(), button, "mScaleUpFactor", mScaleUpFactor);
setField(button.getClass(), button, "mScaleDownFactor", mScaleDownFactor);
// restore
mLargeLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, mLargeLabelSize);
}
}
mMenuView.updateMenuView();
}
/**
* enable the shifting mode for navigation
*
* @param enable It will has a shift animation if true. Otherwise all items are the same width.
*/
public void enableShiftingMode(boolean enable) {
// 1. get mMenuView
BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. change field mShiftingMode value in mMenuView
setField(mMenuView.getClass(), mMenuView, "mShiftingMode", enable);
mMenuView.updateMenuView();
}
/**
* enable the shifting mode for each item
*
* @param enable It will has a shift animation for item if true. Otherwise the item text always be shown.
*/
public void enableItemShiftingMode(boolean enable) {
// 1. get mMenuView
BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. change field mShiftingMode value in mButtons
for (BottomNavigationItemView button : mButtons) {
setField(button.getClass(), button, "mShiftingMode", enable);
}
mMenuView.updateMenuView();
}
/**
* get the current checked item position
*
* @return index of item, start from 0.
*/
public int getCurrentItem() {
// 1. get mMenuView
// 2. get mButtons
BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// 3. get menu and traverse it to get the checked one
Menu menu = getMenu();
for (int i = 0; i < mButtons.length; i++) {
if (menu.getItem(i).isChecked()) {
return i;
}
}
return 0;
}
/**
* get menu item position in menu
*
* @param item
* @return position if success, -1 otherwise
*/
public int getMenuItemPosition(MenuItem item) {
// get item id
int itemId = item.getItemId();
// get meunu
Menu menu = getMenu();
int size = menu.size();
for (int i = 0; i < size; i++) {
if (menu.getItem(i).getItemId() == itemId) {
return i;
}
}
return -1;
}
/**
* set the current checked item
*
* @param item start from 0.
*/
public void setCurrentItem(int item) {
// check bounds
if (item < 0 || item >= getMaxItemCount()) {
throw new ArrayIndexOutOfBoundsException("item is out of bounds, we expected 0 - "
+ (getMaxItemCount() - 1) + ". Actually " + item);
}
// 1. get mMenuView
BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get mButtons
BottomNavigationItemView[] mButtons = getBottomNavigationItemViews();
// get mOnClickListener
View.OnClickListener mOnClickListener = getField(mMenuView.getClass(), mMenuView, "mOnClickListener");
// 3. call mOnClickListener.onClick();
mOnClickListener.onClick(mButtons[item]);
}
/**
* get OnNavigationItemSelectedListener
*
* @return
*/
public OnNavigationItemSelectedListener getOnNavigationItemSelectedListener() {
OnNavigationItemSelectedListener mListener = getField(getClass().getSuperclass(), this, "mListener");
return mListener;
}
@Override
public void setOnNavigationItemSelectedListener(@Nullable OnNavigationItemSelectedListener listener) {
// if not set up with view pager, the same with father
if (null == mMyOnNavigationItemSelectedListener) {
super.setOnNavigationItemSelectedListener(listener);
return;
}
mMyOnNavigationItemSelectedListener.setOnNavigationItemSelectedListener(listener);
}
/**
* get private mMenuView
*
* @return
*/
private BottomNavigationMenuView getBottomNavigationMenuView() {
if (null == mMenuView)
mMenuView = getField(getClass().getSuperclass(), this, "mMenuView");
return mMenuView;
}
/**
* get private mButtons in mMenuView
*
* @return
*/
public BottomNavigationItemView[] getBottomNavigationItemViews() {
if (null != mButtons)
return mButtons;
BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
mButtons = getField(mMenuView.getClass(), mMenuView, "mButtons");
return mButtons;
}
/**
* get private mButton in mMenuView at position
*
* @param position
* @return
*/
public BottomNavigationItemView getBottomNavigationItemView(int position) {
return getBottomNavigationItemViews()[position];
}
/**
* get icon at position
*
* @param position
* @return
*/
public ImageView getIconAt(int position) {
BottomNavigationItemView mButtons = getBottomNavigationItemView(position);
ImageView mIcon = getField(BottomNavigationItemView.class, mButtons, "mIcon");
return mIcon;
}
/**
* get small label at position
* Each item has tow label, one is large, another is small.
*
* @param position
* @return
*/
public TextView getSmallLabelAt(int position) {
BottomNavigationItemView mButtons = getBottomNavigationItemView(position);
TextView mSmallLabel = getField(BottomNavigationItemView.class, mButtons, "mSmallLabel");
return mSmallLabel;
}
/**
* get large label at position
* Each item has tow label, one is large, another is small.
*
* @param position
* @return
*/
public TextView getLargeLabelAt(int position) {
BottomNavigationItemView mButtons = getBottomNavigationItemView(position);
TextView mLargeLabel = getField(BottomNavigationItemView.class, mButtons, "mLargeLabel");
return mLargeLabel;
}
/**
* return item count
*
* @return
*/
public int getItemCount() {
return getBottomNavigationItemViews().length;
}
/**
* set all item small TextView size
* Each item has tow label, one is large, another is small.
* Small one will be shown when item state is normal
* Large one will be shown when item checked.
*
* @param sp
*/
public void setSmallTextSize(float sp) {
int count = getItemCount();
for (int i = 0; i < count; i++) {
getSmallLabelAt(i).setTextSize(sp);
}
mMenuView.updateMenuView();
}
/**
* set all item large TextView size
* Each item has tow label, one is large, another is small.
* Small one will be shown when item state is normal.
* Large one will be shown when item checked.
*
* @param sp
*/
public void setLargeTextSize(float sp) {
int count = getItemCount();
for (int i = 0; i < count; i++) {
getLargeLabelAt(i).setTextSize(sp);
}
mMenuView.updateMenuView();
}
/**
* set all item large and small TextView size
* Each item has tow label, one is large, another is small.
* Small one will be shown when item state is normal
* Large one will be shown when item checked.
*
* @param sp
*/
public void setTextSize(float sp) {
setLargeTextSize(sp);
setSmallTextSize(sp);
}
/**
* set item ImageView size which at position
*
* @param position position start from 0
* @param width in dp
* @param height in dp
*/
public void setIconSizeAt(int position, float width, float height) {
ImageView icon = getIconAt(position);
// update size
ViewGroup.LayoutParams layoutParams = icon.getLayoutParams();
layoutParams.width = dp2px(getContext(), width);
layoutParams.height = dp2px(getContext(), height);
icon.setLayoutParams(layoutParams);
mMenuView.updateMenuView();
}
/**
* set all item ImageView size
*
* @param width in dp
* @param height in dp
*/
public void setIconSize(float width, float height) {
int count = getItemCount();
for (int i = 0; i < count; i++) {
setIconSizeAt(i, width, height);
}
}
/**
* set menu item height
*
* @param height in px
*/
public void setItemHeight(int height) {
// 1. get mMenuView
final BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. set private final int mItemHeight in mMenuView
setField(mMenuView.getClass(), mMenuView, "mItemHeight", height);
mMenuView.updateMenuView();
}
/**
* get menu item height
*
* @return in px
*/
public int getItemHeight() {
// 1. get mMenuView
final BottomNavigationMenuView mMenuView = getBottomNavigationMenuView();
// 2. get private final int mItemHeight in mMenuView
return getField(mMenuView.getClass(), mMenuView, "mItemHeight");
}
/**
* dp to px
*
* @param context
* @param dpValue dp
* @return px
*/
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* set Typeface for all item TextView
*
* @attr ref android.R.styleable#TextView_typeface
* @attr ref android.R.styleable#TextView_textStyle
*/
public void setTypeface(Typeface typeface, int style) {
int count = getItemCount();
for (int i = 0; i < count; i++) {
getLargeLabelAt(i).setTypeface(typeface, style);
getSmallLabelAt(i).setTypeface(typeface, style);
}
mMenuView.updateMenuView();
}
/**
* set Typeface for all item TextView
*
* @attr ref android.R.styleable#TextView_typeface
*/
public void setTypeface(Typeface typeface) {
int count = getItemCount();
for (int i = 0; i < count; i++) {
getLargeLabelAt(i).setTypeface(typeface);
getSmallLabelAt(i).setTypeface(typeface);
}
mMenuView.updateMenuView();
}
/**
* get private filed in this specific object
*
* @param targetClass
* @param instance the filed owner
* @param fieldName
* @param <T>
* @return field if success, null otherwise.
*/
private <T> T getField(Class targetClass, Object instance, String fieldName) {
try {
Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
return (T) field.get(instance);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* change the field value
*
* @param targetClass
* @param instance the filed owner
* @param fieldName
* @param value
*/
private void setField(Class targetClass, Object instance, String fieldName, Object value) {
try {
Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(instance, value);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* This method will link the given ViewPager and this BottomNavigationViewEx together so that
* changes in one are automatically reflected in the other. This includes scroll state changes
* and clicks.
*
* @param viewPager
*/
public void setupWithViewPager(@Nullable final ViewPager viewPager) {
setupWithViewPager(viewPager, false);
}
/**
* This method will link the given ViewPager and this BottomNavigationViewEx together so that
* changes in one are automatically reflected in the other. This includes scroll state changes
* and clicks.
*
* @param viewPager
* @param smoothScroll whether ViewPager changed with smooth scroll animation
*/
public void setupWithViewPager(@Nullable final ViewPager viewPager, boolean smoothScroll) {
if (mViewPager != null) {
// If we've already been setup with a ViewPager, remove us from it
if (mPageChangeListener != null) {
mViewPager.removeOnPageChangeListener(mPageChangeListener);
}
}
if (null == viewPager) {
mViewPager = null;
super.setOnNavigationItemSelectedListener(null);
return;
}
mViewPager = viewPager;
// Add our custom OnPageChangeListener to the ViewPager
if (mPageChangeListener == null) {
mPageChangeListener = new BottomNavigationViewExOnPageChangeListener(this);
}
viewPager.addOnPageChangeListener(mPageChangeListener);
// Now we'll add a navigation item selected listener to set ViewPager's current item
OnNavigationItemSelectedListener listener = getOnNavigationItemSelectedListener();
mMyOnNavigationItemSelectedListener = new MyOnNavigationItemSelectedListener(viewPager, this, smoothScroll, listener);
super.setOnNavigationItemSelectedListener(mMyOnNavigationItemSelectedListener);
}
/**
* A {@link ViewPager.OnPageChangeListener} class which contains the
* necessary calls back to the provided {@link CustomBottomNavigationView} so that the tab position is
* kept in sync.
* <p>
* <p>This class stores the provided BottomNavigationViewEx weakly, meaning that you can use
* {@link ViewPager#addOnPageChangeListener(ViewPager.OnPageChangeListener)
* addOnPageChangeListener(OnPageChangeListener)} without removing the listener and
* not cause a leak.
*/
private static class BottomNavigationViewExOnPageChangeListener implements ViewPager.OnPageChangeListener {
private final WeakReference<CustomBottomNavigationView> mBnveRef;
public BottomNavigationViewExOnPageChangeListener(CustomBottomNavigationView bnve) {
mBnveRef = new WeakReference<>(bnve);
}
@Override
public void onPageScrollStateChanged(final int state) {
}
@Override
public void onPageScrolled(final int position, final float positionOffset,
final int positionOffsetPixels) {
}
@Override
public void onPageSelected(final int position) {
final CustomBottomNavigationView bnve = mBnveRef.get();
if (null != bnve)
bnve.setCurrentItem(position);
}
}
/**
* Decorate OnNavigationItemSelectedListener for setupWithViewPager
*/
private static class MyOnNavigationItemSelectedListener implements OnNavigationItemSelectedListener {
private OnNavigationItemSelectedListener listener;
private final WeakReference<ViewPager> viewPagerRef;
private boolean smoothScroll;
private SparseIntArray items;// used for change ViewPager selected item
private int previousPosition = -1;
MyOnNavigationItemSelectedListener(ViewPager viewPager, CustomBottomNavigationView bnve, boolean smoothScroll, OnNavigationItemSelectedListener listener) {
this.viewPagerRef = new WeakReference<>(viewPager);
this.listener = listener;
this.smoothScroll = smoothScroll;
// create items
Menu menu = bnve.getMenu();
int size = menu.size();
items = new SparseIntArray(size);
for (int i = 0; i < size; i++) {
int itemId = menu.getItem(i).getItemId();
items.put(itemId, i);
}
}
public void setOnNavigationItemSelectedListener(OnNavigationItemSelectedListener listener) {
this.listener = listener;
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int position = items.get(item.getItemId());
// only set item when item changed
if (previousPosition == position) {
return true;
}
// user listener
if (null != listener) {
boolean bool = listener.onNavigationItemSelected(item);
// if the selected is invalid, no need change the view pager
if (!bool)
return false;
}
// change view pager
ViewPager viewPager = viewPagerRef.get();
if (null == viewPager)
return false;
viewPager.setCurrentItem(items.get(item.getItemId()), smoothScroll);
// update previous position
previousPosition = position;
return true;
}
}
}
将原生的直接替换即可
如果不需要动画
直接在初始化空间之后 设置属性即可
navigation.enableAnimation(false);
navigation.enableItemShiftingMode(false);
navigation.enableShiftingMode(false);
以上就是多模块架构 安卓框架搭建(五)增加底部导航栏 的全部详解
如有不了解的 可以去github下载源码 本章节内容为分支5
或 加入安卓开发交流群:安卓帮595856941
相关链接:
下一篇: