Android 底部导航栏有很多种写法,例如:
RadioGroup , Tablayout, TabHost , LinearLayout + ImageView + TextView ,BottomNavigationView
我们就来看最常用的两种底部导航栏的用法
这种是用 LinearLyaout + ImageView + TextView 布局UI, xml 代码如下
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> android:id="@+id/fl_fragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/line"/> android:id="@+id/line" android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/colorTextGrey" android:layout_above="@+id/ll" /> android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:background="@color/bg_white" android:orientation="horizontal" > android:id="@+id/ll_tab1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical"> android:id="@+id/iv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/selector_page1" /> android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="2dp" android:gravity="center" android:text="@string/menu_bottom_navigation1" android:textColor="@color/colorTextGrey" android:textSize="11sp" /> android:id="@+id/ll_tab2" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical"> android:id="@+id/iv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/selector_page2" /> android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="2dp" android:gravity="center" android:text="@string/menu_bottom_navigation2" android:textColor="@color/colorTextGrey" android:textSize="11sp" /> android:id="@+id/ll_tab3" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical"> android:id="@+id/iv3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/selector_page3" /> android:id="@+id/tv3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="2dp" android:gravity="center" android:text="@string/menu_bottom_navigation3" android:textColor="@color/colorTextGrey" android:textSize="11sp" />
此布局最外层是百分比布局 PercentRelativeLayout (适配各种机型屏幕), 而后 是一个
帧布局 FrameLayout(用于Fragment),最后就是这个布局的重点 : 父LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="@color/bg_white"
android:orientation="horizontal"
>
这个LinearLayout , 宽为match_paren, 高为 50dp , 位于父布局底部,子布局水平排列。
有人就会有疑问了:为什么 高为50dp?
因为底部导航栏其实有两种不同标准的高,一个 48dp , 一个 56dp(通过不断积累的经验:这样好看)。
而我给50dp, 算是取个中间整数。
下面看 父 LinearLayout 里面的 第一个 子 LinearLayout
android:id="@+id/ll_tab1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
android:id="@+id/iv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/selector_page1" />
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:gravity="center"
android:text="@string/menu_bottom_navigation1"
android:textColor="@color/colorTextGrey"
android:textSize="11sp" />
这个LinearLayout , 宽为0dp, 高为 match_paren , 权重为1(为了让 子LinearLayout 平分
总LinearLayout 的宽),内容居中, 子布局垂直排列:里面有 ImageView 和 TextView。
第一个子LinearLayout效果:
依葫芦画瓢,按第一个 子Linearlayout 写 第二个 子LinearLayout 和 第三个 子LinearLayout
总效果:
selector_page1 代码:
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android"> - android:drawable="@mipmap/img_1" android:state_enabled="true">
- android:drawable="@mipmap/img_1_selected" android:state_enabled="false">
selector_page2,selector_page3依葫芦画瓢
下面看Activity 代码:
public class BottomNavigationActivity1 extends AppCompatActivity { @BindView(R.id.fl_fragment) FrameLayout flFragment; @BindView(R.id.iv1) ImageView iv1; @BindView(R.id.tv1) TextView tv1; @BindView(R.id.ll_tab1) LinearLayout llTab1; @BindView(R.id.iv2) ImageView iv2; @BindView(R.id.tv2) TextView tv2; @BindView(R.id.ll_tab2) LinearLayout llTab2; @BindView(R.id.iv3) ImageView iv3; @BindView(R.id.tv3) TextView tv3; @BindView(R.id.ll_tab3) LinearLayout llTab3; Unbinder unbinder; Fragment1 fragment1; Fragment2 fragment2; Fragment3 fragment3; private Fragment fragment_now = null; private Listiv_list; private List tv_list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bottom_navigation1); unbinder = ButterKnife.bind(this); inint(); } private void inint() { iv_list = new ArrayList<>(); tv_list = new ArrayList<>(); iv_list.add(iv1); iv_list.add(iv2); iv_list.add(iv3); tv_list.add(tv1); tv_list.add(tv2); tv_list.add(tv3); changePageSelect(0); changePageFragment(R.id.ll_tab1); } @OnClick({R.id.iv1, R.id.ll_tab1, R.id.iv2, R.id.ll_tab2, R.id.iv3, R.id.ll_tab3}) public void onViewClicked(View view) { changePageFragment(view.getId()); } /** * 选中的tab 和 没有选中的tab 的图标和字体颜色 * * @param index */ public void changePageSelect(int index) { for (int i = 0; i < iv_list.size(); i++) { if (index == i) { iv_list.get(i).setEnabled(false); tv_list.get(i).setTextColor(getResources().getColor(R.color.colorLightRed)); } else { iv_list.get(i).setEnabled(true); tv_list.get(i).setTextColor(getResources().getColor(R.color.colorTextGrey)); } } } /** * 当点击导航栏时改变 fragment * * @param id */ public void changePageFragment(int id) { switch (id) { case R.id.ll_tab1: case R.id.iv1: if (fragment1 == null) {//减少new fragmnet,避免不必要的内存消耗 fragment1 = Fragment1.newInstance(); } changePageSelect(0); switchFragment(fragment_now, fragment1); break; case R.id.ll_tab2: case R.id.iv2: if (fragment2 == null) { fragment2 = Fragment2.newInstance(); } changePageSelect(1); switchFragment(fragment_now, fragment2); break; case R.id.ll_tab3: case R.id.iv3: if (fragment3 == null) { fragment3 = Fragment3.newInstance(); } changePageSelect(2); switchFragment(fragment_now, fragment3); break; } } /** * 隐藏显示fragment * * @param from 需要隐藏的fragment * @param to 需要显示的fragment */ public void switchFragment(Fragment from, Fragment to) { if (to == null) return; FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); if (!to.isAdded()) { if (from == null) { transaction.add(R.id.fl_fragment, to).show(to).commit(); } else { // 隐藏当前的fragment,add下一个fragment到Activity中并显示 transaction.hide(from).add(R.id.fl_fragment, to).show(to).commitAllowingStateLoss(); } } else { // 隐藏当前的fragment,显示下一个 transaction.hide(from).show(to).commit(); } fragment_now = to; } @Override protected void onDestroy() { super.onDestroy(); //解除绑定 unbinder.unbind(); } }
首先 build.gradle 添加
implementation 'com.jakewharton:butterknife:8.8.1'
用 butterKnife找到控件并设置点击事件,并用List
List
然后是fragment
Fragment1 代码 :
public class Fragment1 extends Fragment { public Fragment1() { } public static Fragment1 newInstance() { Fragment1 fragment = new Fragment1(); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_1, container, false); } }
Fragment1布局 fragment_1:
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第一个fragment"
android:layout_gravity="center"/>
Fragment2, Fragment3 及其布局 依葫芦画瓢
public void changePageSelect(int index) { for (int i = 0; i < iv_list.size(); i++) { if (index == i) { iv_list.get(i).setEnabled(false); tv_list.get(i).setTextColor(getResources().getColor(R.color.colorLightRed)); } else { iv_list.get(i).setEnabled(true); tv_list.get(i).setTextColor(getResources().getColor(R.color.colorTextGrey)); } } }
public void switchFragment(Fragment from, Fragment to) { if (to == null) return; FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); if (!to.isAdded()) { if (from == null) { transaction.add(R.id.fl_fragment, to).show(to).commit(); } else { // 隐藏当前的fragment,add下一个fragment到Activity中并显示 transaction.hide(from).add(R.id.fl_fragment,to).show(to) .commitAllowingStateLoss(); } } else { // 隐藏当前的fragment,显示下一个 transaction.hide(from).show(to).commit(); } fragment_now = to; }
此方法传入 Fragment form , Fragment to 。 首先判断 Fragment to 是否为 null,
Fragment to为 null 则 return;Fragment to不为 null 往下走得到 FragmnetTranscation transcation。
然后判断 Fragment to 是否添加到Activity,
Fragment to 没有添加到了 Activity 则 判断 Fragment form 是否为 null ,
Fragment form 为 null 则将 Fragment to 添加到Activity 中 并显示;
Fragment form 不为null 则 隐藏Fragment form,将Fragment to 添加到Activity 中 并显示;
Fragment to 添加到了 Activity 则隐藏Fragment form, 显示 Fragment to;
最后将 Fragment to 赋值给 Fragment fragment_now
public void changePageFragment(int id) { switch (id) { case R.id.ll_tab1: case R.id.iv1: if (fragment1 == null) {//减少new fragmnet,避免不必要的内存消耗 fragment1 = Fragment1.newInstance(); } changePageSelect(0); switchFragment(fragment_now, fragment1); break; case R.id.ll_tab2: case R.id.iv2: if (fragment2 == null) { fragment2 = Fragment2.newInstance(); } changePageSelect(1); switchFragment(fragment_now, fragment2); break; case R.id.ll_tab3: case R.id.iv3: if (fragment3 == null) { fragment3 = Fragment3.newInstance(); } changePageSelect(2); switchFragment(fragment_now, fragment3); break; } }
@OnClick({R.id.iv1, R.id.ll_tab1, R.id.iv2, R.id.ll_tab2, R.id.iv3, R.id.ll_tab3}) public void onViewClicked(View view) { changePageFragment(view.getId()); }
changepageFragment() 的妙处就是调用 switchFragment() 第一个参数 传了 Fragment fragment_now,
这样 Fragment fragment_now() 与 switchFragment() 就通过 Fragment fragment_now 紧密联系起来
绝多数app都用底部导航栏,所以 google 爸爸为了方便开发者在 Design Support Library中添加了 BotoomNavigationView控件,我们就不用苦逼的LinearLyaout + ImageView + TextView 布局写法了!
首先 build.gradle 添加
implementation 'com.android.support:design:27.0.1'
然后布局:
xml version="1.0" encoding="utf-8"?>app:itemIconTint 为图标颜色变化 , app:itemtextColor 为为文字 颜色变化xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > android:id="@+id/fl_fragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/bottomNavigationView" /> android:id="@+id/bottomNavigationView" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" app:itemIconTint="@drawable/selector_bottom_navigation" app:itemTextColor="@drawable/selector_bottom_navigation" app:menu="@menu/menu_bottom_navigation" />
然后在drawable下 创建 selector_bottom_navigantion
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android"> - android:state_checked="true" android:color="@color/colorLightGreen" />
- android:state_checked="false" android:color="@color/colorTextGrey" />
然后在res 创建 menu文件夹,并在下面创建 menu_bottom_navigation
xml version="1.0" encoding="utf-8"?>
最后Activity代码
public class BottomNavigationActivity2 extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener{
@BindView(R.id.fl_fragment)
FrameLayout flFragment;
@BindView(R.id.bottomNavigationView)
BottomNavigationView bottomNavigationView;
Unbinder unbinder;
Fragment1 fragment1;
Fragment2 fragment2;
Fragment3 fragment3;
private Fragment fragment_now = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_navigation2);
unbinder = ButterKnife.bind(this);
inint();
}
@SuppressLint("NewApi")
private void inint() {
bottomNavigationView.setOnNavigationItemSelectedListener(this);//设置 NavigationItemSelected 事件监听
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);//改变 BottomNavigationView 默认的效果
//选中第一个item,对应第一个fragment
bottomNavigationView.setSelectedItemId(R.id.item_1);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbinder.unbind();
}
//NavigationItemSelected 事件监听
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
changePageFragment(item.getItemId());
return true;
}
/**
* 当点击导航栏时改变fragment
*
* @param id
*/
public void changePageFragment(int id) {
switch (id) {
case R.id.item_1:
if (fragment1 == null) { //减少new fragmnet,避免不必要的内存消耗
fragment1 = Fragment1.newInstance();
}
switchFragment(fragment_now, fragment1);
break;
case R.id.item_2:
if (fragment2 == null) {
fragment2 = Fragment2.newInstance();
}
switchFragment(fragment_now, fragment2);
break;
case R.id.item_3:
if (fragment3 == null) {
fragment3 = Fragment3.newInstance();
}
switchFragment(fragment_now, fragment3);
break;
}
}
/**
* 隐藏显示fragment
*
* @param from 需要隐藏的fragment
* @param to 需要显示的fragment
*/
public void switchFragment(Fragment from, Fragment to) {
if (to == null)
return;
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (!to.isAdded()) {
if (from == null) {
transaction.add(R.id.fl_fragment, to).show(to).commit();
} else {
// 隐藏当前的fragment,add下一个fragment到Activity中
transaction.hide(from).add(R.id.fl_fragment, to).commitAllowingStateLoss();
}
} else {
// 隐藏当前的fragment,显示下一个
transaction.hide(from).show(to).commit();
}
fragment_now = to;
}
}
switchFragment() 与第一种写法一致; changePageFragment() 与第一种写法区别在于没有changePageSelect(), 因为BottomNavigationView 已经在布局app:itemIconTint 与 app:itemtextColor做了这个事。
最后设置 BottomNavigationView 的 item 选择事件监听调用changePageFragment()
public class BottomNavigationActivity2 extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener
bottomNavigationView.setOnNavigationItemSelectedListener(this); @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { changePageFragment(item.getItemId()); return true; }
如果BottomNavigationView 的 item >3 则会出现 位移效果,而我们不要位移效果怎么办?
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);
public class BottomNavigationViewHelper { @RequiresApi(api = Build.VERSION_CODES.KITKAT) @SuppressLint("RestrictedApi") public static void disableShiftMode(BottomNavigationView navigationView) { BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigationView.getChildAt(0); try { // 利用反射,改变 item 中 mShiftingMode 的值 ,从而改变 BottomNavigationView 默认的效果 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 itemView = (BottomNavigationItemView) menuView.getChildAt(i); itemView.setShiftingMode(false); itemView.setChecked(itemView.getItemData().isChecked()); } } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } }
有人会问:这样为什么可以改变默认大小?
在此先简单分析(以后分析BottomNavigationView源码 ):
通过 BottomNavigationView 找到 BottomNavigationMenuView , 在BottomNavigationMenuView 看到
private boolean mShiftingMode = true;
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = MeasureSpec.getSize(widthMeasureSpec); final int count = getChildCount(); final int heightSpec = MeasureSpec.makeMeasureSpec(mItemHeight, MeasureSpec.EXACTLY); if (mShiftingMode) { final int inactiveCount = count - 1; final int activeMaxAvailable = width - inactiveCount * mInactiveItemMinWidth; final int activeWidth = Math.min(activeMaxAvailable, mActiveItemMaxWidth); final int inactiveMaxAvailable = (width - activeWidth) / inactiveCount; final int inactiveWidth = Math.min(inactiveMaxAvailable, mInactiveItemMaxWidth); int extra = width - activeWidth - inactiveWidth * inactiveCount; for (int i = 0; i < count; i++) { mTempChildWidths[i] = (i == mSelectedItemPosition) ? activeWidth : inactiveWidth; if (extra > 0) { mTempChildWidths[i]++; extra--; } } } else { final int maxAvailable = width / (count == 0 ? 1 : count); final int childWidth = Math.min(maxAvailable, mActiveItemMaxWidth); int extra = width - childWidth * count; for (int i = 0; i < count; i++) { mTempChildWidths[i] = childWidth; if (extra > 0) { mTempChildWidths[i]++; extra--; } } } int totalWidth = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } child.measure(MeasureSpec.makeMeasureSpec(mTempChildWidths[i], MeasureSpec.EXACTLY), heightSpec); ViewGroup.LayoutParams params = child.getLayoutParams(); params.width = child.getMeasuredWidth(); totalWidth += child.getMeasuredWidth(); } setMeasuredDimension( View.resolveSizeAndState(totalWidth, MeasureSpec.makeMeasureSpec(totalWidth, MeasureSpec.EXACTLY), 0), View.resolveSizeAndState(mItemHeight, heightSpec, 0)); }
BottomNavigationMenuView 通过 mShiftingMode 为标识 , measure 它的各子view 的宽高,而宽在不断变化,从而产生位移变化。
有人会问:为什么是item >3 则会出现 位移效果?
因为在BottomNavigationMenuView 的 buildMenuView()中的mShiftingMode = mMenu.size() > 3
public void buildMenuView() { removeAllViews(); if (mButtons != null) { for (BottomNavigationItemView item : mButtons) { mItemPool.release(item); } } if (mMenu.size() == 0) { mSelectedItemId = 0; mSelectedItemPosition = 0; mButtons = null; return; } mButtons = new BottomNavigationItemView[mMenu.size()]; 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); } mSelectedItemPosition = Math.min(mMenu.size() - 1, mSelectedItemPosition); mMenu.getItem(mSelectedItemPosition).setChecked(true); }
如果你想有滑动切换效果,可以 添加 ViewPager
build.gradle 添加
implementation 'com.android.support:support-v4:27.0.1'
布局修改为
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/bottomNavigationView" /> android:id="@+id/bottomNavigationView" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" app:itemIconTint="@drawable/selector_bottom_navigation" app:itemTextColor="@drawable/selector_bottom_navigation" app:menu="@menu/menu_bottom_navigation" />
Activity代码修改为
public class BottomNavigationActivity2 extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener,ViewPager.OnPageChangeListener,ViewPager.OnTouchListener{ @BindView(R.id.bottomNavigationView) BottomNavigationView bottomNavigationView; @BindView(R.id.viewpager) ViewPager viewPager; Unbinder unbinder; Fragment1 fragment1; Fragment2 fragment2; Fragment3 fragment3; BottomnavigationViewPagerAdapter pagerAdapter; Listfragments; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bottom_navigation2); unbinder = ButterKnife.bind(this); inint(); } @SuppressLint("NewApi") private void inint() { fragments = new ArrayList<>(); fragment1 = Fragment1.newInstance(); fragment2 = Fragment2.newInstance(); fragment3 = Fragment3.newInstance(); if(!fragments.contains(fragment1)){ fragments.add(fragment1); } if(!fragments.contains(fragment2)){ fragments.add(fragment2); } if(!fragments.contains(fragment3)){ fragments.add(fragment3); } bottomNavigationView.setOnNavigationItemSelectedListener(this);//设置 NavigationItemSelected 事件监听 BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);//改变 BottomNavigationView 默认的效果 //选中第一个item,对应第一个fragment bottomNavigationView.setSelectedItemId(R.id.item_1); pagerAdapter = new BottomnavigationViewPagerAdapter(getSupportFragmentManager(),fragments); viewPager.setAdapter(pagerAdapter); viewPager.addOnPageChangeListener(this); // 如果想禁止滑动,可以把下面的代码取消注释 // viewPager.setOnTouchListener(this); } @Override protected void onDestroy() { super.onDestroy(); unbinder.unbind(); } //NavigationItemSelected 事件监听 @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()){ case R.id.item_1: viewPager.setCurrentItem(0); break; case R.id.item_2: viewPager.setCurrentItem(1); break; case R.id.item_3: viewPager.setCurrentItem(3); break; } return true; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { bottomNavigationView.getMenu().getItem(position).setChecked(true); } @Override public void onPageScrollStateChanged(int state) { } @Override public boolean onTouch(View v, MotionEvent event) { return true; } }
最后 注意BottomNavigationView item 范围 1~5 个 (早期版本是 3~5 个)
public final class BottomNavigationMenu extends MenuBuilder { public static final int MAX_ITEM_COUNT = 5; .............. @Override protected MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) { if (size() + 1 > MAX_ITEM_COUNT) { throw new IllegalArgumentException( "Maximum number of items supported by BottomNavigationView is " + MAX_ITEM_COUNT + ". Limit can be checked with BottomNavigationView#getMaxItemCount()"); } stopDispatchingItemsChanged(); final MenuItem item = super.addInternal(group, id, categoryOrder, title); if (item instanceof MenuItemImpl) { ((MenuItemImpl) item).setExclusiveCheckable(true); } startDispatchingItemsChanged(); return item; } }
最后效果
代码地址:https://github.com/ccWenTian/notes, 如果觉得还行,请点个赞。