一. 前言

这是Google官方提供的一个BottomNavigationView。目前用的时候需要自己添加依赖,或者在布局文中搜搜索该控件,然后下载同步即可。

下面是运行效果:

二. demo

1. Fragment

我们首先需要四个Fragment,四个Fragment的代码都是一样的,只是名称不一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//Fragment的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>

</RelativeLayout>

//Fragment
public class FragmentOne extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_layout, container, false);

TextView textView = inflate.findViewById(R.id.text);
Bundle arguments = getArguments();
String text = arguments.getString("text", "");
textView.setText(text);

return inflate;
}
}

2. 创建布局

① 首先需要准备好BottomNavigationView的tab_menu.xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/tab_home"
android:icon="@drawable/home"
android:title="首页"
/>

<item
android:id="@+id/tab_shop"
android:icon="@drawable/shop"
android:title="购物"
/>

<item
android:id="@+id/tab_bill"
android:icon="@drawable/bill"
android:title="消费"
/>

<item
android:id="@+id/tab_personal"
android:icon="@drawable/personal"
android:title="个人"
/>
</menu>

② 在主布局文件中添加ViewPager和BottomNavigationView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottom_view"
/>

<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#fcfcfc"
app:menu="@menu/tab_menu"
app:itemIconTint="@color/menu_color"
app:itemTextColor="@color/menu_color"
app:itemBackground="@null"
app:labelVisibilityMode="auto"
/>

</RelativeLayout>

1> 其中app:itemIconTint是设置选中和没有选中的图标颜色,itemTextColor是设置选中和没有选中的字体颜色。参考文章:【Android】BottomNavigationView底部导航栏自定义选中颜色

color文件夹中的menu_color.xml文件如下:

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#9966cc" android:state_checked="true"/>
<item android:color="#a2c699" android:state_checked="false"/>
</selector>

2> itemBackground设置为@null可以去除点击的水波纹效果。

3> labelVisibilityMode共有四个值:auto,unlabeled,labeled,selected。这几个属性根据MenuItem不同的数量可以设置不同的效果。如,当我们设置为unlabeled时,你会发现文字不显示了。当我们设置为labeled时,你会发现切换的缩放的时候所有的文字都是显示的。

1
2
3
4
auto   当item小于等于3是,显示文字,item大于3个默认不显示,选中显示文字
labeled 始终显示文字
selected 选中时显示
unlabeled 选中时显示

4> 移除动画效果

第一种说法,参考文章-使用新版的BottomNavigationView当Item大于3时,去除动画很简单

设置app:itemHorizontalTranslationEnabled=”false”` 就禁止item水平平移动画效果,但是我没有效果。

第二种说法,参考文章-二行代码去掉Android BottomNavigationView图标和文字缩放动画效

通过设置选中前后的效果一致,达到去掉的效果

1
2
3
BottomNavigationView bottomNavigationView = findViewById(R.id.navigation);
bottomNavigationView.setItemTextAppearanceActive(R.style.bottom_selected_text);
bottomNavigationView.setItemTextAppearanceInactive(R.style.bottom_normal_text);

第三种说法,参考文章-Android:BottomNavigationView的使用和去掉动画效果

dimens里把文字大小设置为一样就不会放大了

1
2
<dimen name="design_bottom_navigation_active_text_size">12sp</dimen>
<dimen name="design_bottom_navigation_text_size">12sp</dimen>

3. ViewPager+Fragment

这个内容之前说过,可以查看我之前的ViewPager的文章。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//找到控件
final ViewPager viewPager = findViewById(R.id.view_pager);

//数据源
List<Fragment> fragments = new ArrayList<>();

FragmentOne fragmentOne = new FragmentOne();
Bundle bundle1 = new Bundle();
bundle1.putString("text","home");
fragmentOne.setArguments(bundle1);
fragments.add(fragmentOne);

FragmentTwo fragmentTwo = new FragmentTwo();
Bundle bundle2 = new Bundle();
bundle2.putString("text","shop");
fragmentTwo.setArguments(bundle2);
fragments.add(fragmentTwo);

FragmentThree fragmentThree = new FragmentThree();
Bundle bundle3 = new Bundle();
bundle3.putString("text","bill");
fragmentThree.setArguments(bundle3);
fragments.add(fragmentThree);

FragmentFour fragmentFour = new FragmentFour();
Bundle bundle4 = new Bundle();
bundle4.putString("text","person");
fragmentFour.setArguments(bundle4);
fragments.add(fragmentFour);

//设置适配器
viewPager.setAdapter(
new MyAdapterFragment(
getSupportFragmentManager(),
fragments,
FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
)
);

public class MyAdapterFragment extends FragmentPagerAdapter {
//fragment数据集合
List<Fragment> fragments;

//构造方法
public MyAdapterFragment(@NonNull FragmentManager fm, List<Fragment> fragments, int behavior) {
super(fm, behavior);

this.fragments = fragments;
}

@NonNull
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}

@Override
public int getCount() {
return fragments.size();
}
}

4. 互相绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//BottomNavigationView点击事件监听
final BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_view);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
//跳转到指定页面
switch (menuItem.getItemId()){
case R.id.tab_home:
viewPager.setCurrentItem(0);
break;
case R.id.tab_shop:
viewPager.setCurrentItem(1);
break;
case R.id.tab_bill:
viewPager.setCurrentItem(2);
break;
case R.id.tab_personal:
viewPager.setCurrentItem(3);
break;
}

return true;
}
});

//ViewPager点击事件监听
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@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) {

}
});

5. 额外补充

参考文章-基于android P(9.0)版本的BottomNavigationView使用教程,其中有关于设置间隔大小,设置水波纹效果的说明。

参考文章

Android进阶之路 - BottomNavigationView的使用与问题处理方案

BottomNavigationView+ViewPager+Fragment 底部导航按钮