Android底部导航栏最常用的两种写法

先来看看底部导航栏的效果




Android 底部导航栏有很多种写法,例如:

         RadioGroup Tablayout, TabHost  , LinearLayout + ImageView + TextView BottomNavigationView


我们就来看最常用的两种底部导航栏的用法

                                     

                     一. LinearLayout  + ImageView + TextView


    这种是用  LinearLyaout + ImageView + TextView 布局UI,  xml 代码如下

<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/fl_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/line"/>
    <View
        android:id="@+id/line"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/colorTextGrey"
        android:layout_above="@+id/ll"
        />
    <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
            android:id="@+id/ll_tab1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">
            <ImageView
                android:id="@+id/iv1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/selector_page1" />
            <TextView
                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>
        <LinearLayout
            android:id="@+id/ll_tab2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">
            <ImageView
                android:id="@+id/iv2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/selector_page2" />
            <TextView
                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" />
        </LinearLayout>
        <LinearLayout
            android:id="@+id/ll_tab3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">
            <ImageView
                android:id="@+id/iv3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/selector_page3" />
            <TextView
                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" />
        </LinearLayout>
    </LinearLayout>
</android.support.percent.PercentRelativeLayout>

     此布局最外层是百分比布局 PercentRelativeLayout (适配各种机型屏幕), 而后   是一个

     帧布局 FrameLayout(用于Fragment),最后就是这个布局的重点 :  父LinearLayout

<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

<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">
    <ImageView
        android:id="@+id/iv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/selector_page1" />
    <TextView
        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>

 

这个LinearLayout  ,  宽为0dp, 高为 match_paren , 权重为1(为了让 子LinearLayout 平分

总LinearLayout 的宽),内容居中, 子布局垂直排列:里面有 ImageView 和 TextView。

第一个子LinearLayout效果:       

        

                              

   依葫芦画瓢,按第一个 子Linearlayout 写 第二个 子LinearLayout 和 第三个 子LinearLayout 


   总效果:



          


   selector_page1 代码:


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/img_1" android:state_enabled="true"></item>
    <item android:drawable="@mipmap/img_1_selected" android:state_enabled="false"></item>

 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 List<ImageView> iv_list;
    private List<TextView> 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 {
                // 隐藏当前的fragmentadd下一个fragmentActivity中并显示
                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<ImageView>  iv_list 将 ImageView add,

List<TextView> tv_list将 TextView add,


然后是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:


<FrameLayout 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"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="第一个fragment"
        android:layout_gravity="center"/>
</FrameLayout>

Fragment2, Fragment3 及其布局 依葫芦画瓢


然后写changePageSelect() 改变 选中的tab 和 没有选中的tab 的图标和字体颜色


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));
        }
    }
}


然后写switchFragment() 添加 ,显示, 隐藏 frament


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 {
            // 隐藏当前的fragmentadd下一个fragmentActivity中并显示
             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


最后写changepageFragment() , 调用 changePageSelect() 与 switchFragment() 并给点击事件调用


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 紧密联系起来



到此底部导航栏 LinearLyaout + ImageView + TextView 的写法到此就介绍完毕了!



                                        二.  BotoomNavigationView

 

绝多数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"?>
<android.support.percent.PercentRelativeLayout 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"
   >
    <FrameLayout
        android:id="@+id/fl_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/bottomNavigationView"
        />
    <android.support.design.widget.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"
        />
</android.support.percent.PercentRelativeLayout>
app:itemIconTint 为图标颜色变化 , app:itemtextColor 为为文字 颜色变化



然后在drawable下 创建 selector_bottom_navigantion


<?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/colorLightGreen"  />
    <item  android:state_checked="false" android:color="@color/colorTextGrey" />
</selector>


然后在res 创建 menu文件夹,并在下面创建 menu_bottom_navigation


<?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/item_1"
        android:icon="@mipmap/img_1"
        android:title="@string/menu_bottom_navigation1"
        />
    <item
        android:id="@+id/item_2"
        android:icon="@mipmap/img_2"
        android:title="@string/menu_bottom_navigation2"
      />

    <item
        android:id="@+id/item_3"
        android:icon="@mipmap/img_3"
        android:title="@string/menu_bottom_navigation3"
        />
</menu>


最后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 {
                // 隐藏当前的fragmentadd下一个fragmentActivity                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"?>
<android.support.percent.PercentRelativeLayout 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"
   >
    <!--<FrameLayout-->
        <!--android:id="@+id/fl_fragment"-->
        <!--android:layout_width="match_parent"-->
        <!--android:layout_height="match_parent"-->
        <!--android:layout_above="@+id/bottomNavigationView"-->
        <!--/>-->
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/bottomNavigationView" />
    <android.support.design.widget.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"
        />
</android.support.percent.PercentRelativeLayout>


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;
    List<Fragment> fragments;
    @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;
    }
}


到此底部导航栏 BottomNavigationView 的用法到此就介绍完毕了!


最后效果



 


代码地址:https://github.com/ccWenTian/notes,   如果觉得还行,请点个赞。







         

  • 35
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值