关于BottomNavigationView的使用姿势都在这里了

2023-10-28

一,基本用法

1,首先需要添加依赖:

implementation 'com.google.android.material:material:1.1.0'

2,布局文件中引入:

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/nav_view"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="0dp"
    android:layout_marginEnd="0dp"
    android:background="?android:attr/windowBackground"
    app:menu="@menu/bottom_nav_menu" />

   
   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3,常用属性:

  • app:itemTextColor 文字的颜色,可以通过selector来控制选中和未选中的颜色

  • app:itemIconTint 图标的颜色,可以通过selector来控制选中和未选中的颜色

  • app:itemIconSize 图标大小,默认24dp

  • app:iteamBackground 背景颜色,默认是主题的颜色

  • app:itemRippleColor 点击后的水波纹颜色

  • app:itemTextAppearanceActive 设置选中时文字样式

  • app:itemTextAppearanceInactive 设置默认的文字样式

  • app:itemHorizontalTranslationEnabled 在label visibility 模式为selected时item水平方向移动

  • app:elevation 控制控件顶部的阴影

  • app:labelVisibilityMode 文字的显示模式

  • app:menu 指定菜单xml文件(文字和图片都写在这个里面)

4,menu文件:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/navigation_item1"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/title_size" />
    <item
        android:id="@+id/navigation_item2"
        android:icon="@drawable/ic_dashboard_black_24dp"
        android:title="@string/title_style" />
    <item
        android:id="@+id/navigation_item3"
        android:icon="@drawable/ic_notifications_black_24dp"
        android:title="@string/title_in_list" />
</menu>

   
   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

​ 在每个item中设置对应的icon和title即可。这里的icon可以是一个drawable,也可以是包含不同状态对应不同图片的selector

​ 设置了menu后一个基本的底部菜单栏就有了。
在这里插入图片描述

5,常用事件

​ 主要用两个事件OnNavigationItemSelectedListenerOnNavigationItemReselectedListener

nav_view.setOnNavigationItemSelectedListener(
    BottomNavigationView.OnNavigationItemSelectedListener {
    when (it.itemId) {
        R.id.navigation_item1 -> {
            Log.e("bottomMenuView:", "home")
            return@OnNavigationItemSelectedListener true
        }
        R.id.navigation_item2 -> {
            Log.e("bottomMenuView:", "dashboard")
            return@OnNavigationItemSelectedListener true
        }
        R.id.navigation_item3 -> {
            Log.e("bottomMenuView:", "notification")
            return@OnNavigationItemSelectedListener true
        }
    }
    false
})

   
   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
nav_view.setOnNavigationItemReselectedListener(
    BottomNavigationView.OnNavigationItemReselectedListener {
    Log.e("bottomMenuView:", it.itemId.toString())
})

   
   
   
   
  • 1
  • 2
  • 3
  • 4

​ 两个事件的用法是一样的,区别在于:OnNavigationItemSelectedListener在item由未选中到选中状态时触发,而OnNavigationItemReselectedListener在item处于选中状态再次点击时触发。

6,最大Item数量

BottomNavigationView对显示的item数量做了显示,最多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()");
    }
    // ...
    return item;
  }
}

   
   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

​ google这么做的原因大概是一般不会有超过5个的需求,而且超过5个以后就会显得很拥挤,UI效果比较差。

二,配合fragment

​ 单纯使用BottomNavigationView并没有什么卵用,一般都是配合fragment来使用。配合fragment使用时有三种方式:

1,FrameLayout + FragmentTransaction

​ 比较古老的一种方式通过getSupportFragmentManager().beginTransaction()获取到FragmentTransaction,然后通过FragmentTransactionaddshowhide等方法来控制fragment的显示,这种方式比较繁琐就不赘述了。

2,ViewPager

ViewPager一种比较流行的方式,当然你也可以用ViewPager2,用法差不多。需要在布局文件中添加ViewPager

2.1,设置ViewPager的adapter,如下:

mFragments.add(Fragment1.newInstance())
mFragments.add(Fragment2.newInstance())
mFragments.add(Fragment3.newInstance())
val adapter = object :
    FragmentStatePagerAdapter(
        supportFragmentManager,
        BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
    ) {
    override fun getItem(position: Int): Fragment {
        return mFragments[position]
    }
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">getCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> Int <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">return</span> mFragments<span class="token punctuation">.</span>size
<span class="token punctuation">}</span>

}

viewPager.adapter = adapter

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

​ 然后需要将ViewPagerBottomNavigationView绑定。

2.2,ViewPager绑定BottomNavigationView

​ 就是在ViewPager切换时更改BottomNavigationView选中项

// 添加viewpager切换监听
viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
    // ...
    override fun onPageSelected(position: Int) {
        when (position) {
            0 -> {
                navigation.selectedItemId = R.id.navigation_item1
            }
            1 -> {
                navigation.selectedItemId = R.id.navigation_item2
            }
            2 -> {
                navigation.selectedItemId = R.id.navigation_item3
            }
        }
    }
})

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

2.3,BottomNavigationView绑定ViewPager

​ 同样的,需要在BottomNavigationView选中项改变时更改ViewPager:

navigation.setOnNavigationItemSelectedListener(
    BottomNavigationView.OnNavigationItemSelectedListener { item ->
                when (item.itemId) {
                    R.id.navigation_item1 -> {
                        viewPager.currentItem = 0
                        return@OnNavigationItemSelectedListener true
                    }
                    R.id.navigation_item2 -> {
                        viewPager.currentItem = 1
                        return@OnNavigationItemSelectedListener true
                    }
                    R.id.navigation_item3 -> {
                        viewPager.currentItem = 2
                        return@OnNavigationItemSelectedListener true
                    }
                }
                false
            })

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3,配合navigation

​ 这种方式是Google官方目前主推的方式,需要你对navigation有所了解。

​ 1,布局文件如下:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>com.google.android.material.bottomnavigation.BottomNavigationView</span>
    <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/nav_view<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0dp<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>layout_marginStart</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0dp<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>layout_marginEnd</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0dp<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>background</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>?android:attr/windowBackground<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintBottom_toBottomOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintLeft_toLeftOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintRight_toRightOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>menu</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@menu/bottom_nav_menu<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fragment</span>
    <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/nav_host_fragment<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>androidx.navigation.fragment.NavHostFragment<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>defaultNavHost</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintBottom_toTopOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@id/nav_view<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintLeft_toLeftOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintRight_toRightOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintTop_toTopOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">app:</span>navGraph</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@navigation/mobile_navigation<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

</androidx.constraintlayout.widget.ConstraintLayout>

  • 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

​ 2,navigation文件

<navigation 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/mobile_navigation"
    app:startDestination="@+id/navigation_home">
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fragment</span>
    <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/navigation_item1<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>per.wsj.bottommenu.ui.fragment.Fragment1<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>label</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@string/title_home<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">tools:</span>layout</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@layout/fragment_home<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fragment</span>
    <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/navigation_item2<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>per.wsj.bottommenu.ui.fragment.Fragment2<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>label</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@string/title_dashboard<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">tools:</span>layout</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@layout/fragment_dashboard<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fragment</span>
    <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/navigation_item2<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>per.wsj.bottommenu.ui.fragment.Fragment3<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">android:</span>label</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@string/title_notifications<span class="token punctuation">"</span></span>
    <span class="token attr-name"><span class="token namespace">tools:</span>layout</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@layout/fragment_notifications<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>

</navigation>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

​ 在navigation中指定了对应的fragment

​ 3,Activity中

​ 接下来的使用就很简单了,调用Activity的扩展函数findNavController,根据布局文件中的fragment标签的id获取NavController,将NavControllerBottomNavigationView绑定即可,如下:

val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
navView.setupWithNavController(navController)

 
 
 
 
  • 1
  • 2
  • 3

​ 效果如下:
在这里插入图片描述

三,显示badge(角标/悬浮徽章)

​ 还在github上查找怎么往BottomNavigationView上添加badge吗?BottomNavigationView默认提供了badge。

​ 1,基本使用

​ 在BottomNavigationView上添加badge很简单,它提供了如下操作badge的方法:

  • getBadge(int menuItemId) 获取badge

  • getOrCreateBadge(int menuItemId) 获取或创建badge

  • removeBadge(int menuItemId) 移除badge

    因此添加一个badge只需要如下代码:

val navView: BottomNavigationView = findViewById(R.id.nav_view)
val badge = navView.getOrCreateBadge(R.id.navigation_dashboard)

 
 
 
 
  • 1
  • 2

​ 效果如下:
在这里插入图片描述

​ 纳尼?怎么只有一个红点,胸弟别鸡动,还没设置数量

badge.number = 20

 
 
 
 
  • 1

​ 添加数量后效果如下:
在这里插入图片描述

​ 2,常用属性

getBadgegetOrCreateBadge方法返回的都是BadgeDrawableBadgeDrawable常用的属性/方法如下:

  • backgroundColor 设置背景色

  • badgeGravity 设置Badge的显示位置,有四种可先:TOP_STARTTOP_ENDBOTTOM_STARTBOTTOM_END,分别对应左上角,右上角,左下角和右下角。

  • badgeTextColor 设置文字颜色

  • maxCharacterCount 最多显示几位数字,比如该项设置了3,number设置为108,则显示99+,如下图所示:
    在这里插入图片描述

​ 3,注意事项

​ 需要你Application的Theme继承自Theme.MaterialComponents,如下所示:

<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

​ 4,扩展

​ 同样是位于com.google.android.material包中的TabLayout也可以用同样的方式添加badge

    tabLayout.getTabAt(0).orCreateBadge.apply {
        number = 10
        backgroundColor = Color.RED
    }

 
 
 
 
  • 1
  • 2
  • 3
  • 4

四,常用需求

1,动态显示/隐藏MenuItem

​ 有些时候需要根据条件来控制menuItem是否显示,有两种方式可以实现:

​ 1.1, remove

val navView: BottomNavigationView = findViewById(R.id.nav_view)
navView.menu.removeItem(R.id.navigation_spacing)

 
 
 
 
  • 1
  • 2

​ 这种方式是直接把这个item删除掉了,是一个不可逆的过程,也就是说删除后没法再显示出来

​ 1.2, setVisible

// 显示
nav_view.menu.findItem(R.id.navigation_test).isVisible = true
// 隐藏
nav_view.menu.findItem(R.id.navigation_test).isVisible = false

 
 
 
 
  • 1
  • 2
  • 3
  • 4

​ 效果如下:
在这里插入图片描述

2,更改字体颜色

​ 创建selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#ff0000" android:state_checked="true"/>
    <item android:color="#00CC00" android:state_checked="false"/>
</selector>

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

​ 设置app:itemTextColor属性:

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/nav_view"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:background="?android:attr/windowBackground"
    app:itemTextColor="@drawable/selector_menu_text_color"
    app:menu="@menu/bottom_nav_menu" />

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

​ 效果如下:
在这里插入图片描述

3,修改字体大小

​ 字体大小分为选中的大小和未选中的大小,他们的默认值分别是14sp/12sp,可以通过覆盖原来的字体大小来改变字体大小。

<!--默认字体大小 -->
<dimen name="design_bottom_navigation_text_size">14sp</dimen>
<!--选中字体大小 -->
<dimen name="design_bottom_navigation_active_text_size">14sp</dimen>

 
 
 
 
  • 1
  • 2
  • 3
  • 4

​ 修改前后的效果:
在这里插入图片描述
在这里插入图片描述

4,自定义选中图标颜色

​ 图标的颜色是通过着色实现的,如果我们的图标不是纯色就需要特殊处理了。

​ 比如如下图标:
在这里插入图片描述

​ 可以通过selector来定义选中和未选中的状态,并设置给menu itemicon

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

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5

​ 然后在activity中设置itemIconTintList为null

nav_view.itemIconTintList = null

 
 
 
 
  • 1

​ 效果如下:
在这里插入图片描述

5,labelVisibilityMode

​ 在前面基本属性中已经提到,文字的显示模式有四种:

  • auto

    ​ 这种模式就是item数量在三个及以下全部显示label,三个以上只显示选中item的label,效果如下:
    在这里插入图片描述

  • selected

    ​ 该模式下,不管item数量是多少都只显示选中的item的label
    在这里插入图片描述

  • labeled

    该模式下,不管item数量是多少item的label都显示
    在这里插入图片描述

  • unlabeled

    该模式下,item的label始终不显示
    在这里插入图片描述

    label的显示模式可以在布局文件中通过labelVisibilityMode设置,也可以在java代码中通过setLabelVisibilityMode设置

6,切换时的动画效果?

​ 很多人说切换时会有动画效果,如下:
在这里插入图片描述

​ 其实这并不是什么动画效果,只是因为选中时文字的字体变大了(实际上是两个字体大小不一样的TextView切换显示状态),把图标撑起来了,再加上点击时的Ripple效果,感觉就是一个高大上的动效。要去掉这个效果只需要将字体选中和默认的大小改成一致即可,效果如下:
在这里插入图片描述

7,图标文字间距

​ 7.1 调整图标到顶部的距离

​ 如果想调整图标和文字间的距离,改怎么办呢?查了一些资料大部分都是通过添加dimen覆盖默认的design_bottom_navigation_margin来实现。

<dimen name="design_bottom_navigation_margin">4dp</dimen>

 
 
 
 
  • 1

​ 该值默认是把8dp,把它调小了,发现图标和文字的距离变大了,这是怎么回事?其实这个距离并不是图标和文字的间距,而是图标距离顶部和底部的Margin值,调小后到顶部的距离也变小了,就显得图标和文字的距离变大了。

​ 如果你有显示badge的需求,那这种方式就出问题了,因为badge是依附于图标的,图标上移,badge也会跟着上移,可以就显示不全了
在这里插入图片描述

​ 7.2 调整文字到底部的距离

​ 那么如果我想调整文字到底部的距离呢?这就需要了解一下每个Item的布局文件design_bottom_navigation_item.xml,其源代码(部分代码省略)如下:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
  <ImageView
      android:id="@+id/icon"
      android:layout_width="24dp"
      android:layout_height="24dp"
      android:layout_marginTop="@dimen/design_bottom_navigation_margin"
      android:layout_marginBottom="@dimen/design_bottom_navigation_margin"
      android:layout_gravity="center_horizontal"/>
  <com.google.android.material.internal.BaselineLayout
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="bottom|center_horizontal"
      android:paddingBottom="10dp">
    <TextView
        android:id="@+id/smallLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/design_bottom_navigation_text_size"/>
    <TextView
        android:id="@+id/largeLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/design_bottom_navigation_active_text_size"
        android:visibility="invisible"/>
  </com.google.android.material.internal.BaselineLayout>
</merge>

 
 
 
 
  • 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

​ 可见如果想修改文字到底部的距离可以改动其父容器BaselineLayoutbottomMargin属性,或调用父容器的scrollBy()使内部的TextView向下偏移,当然此时就需要用到反射。

public static void hookBnv(BottomNavigationView menu) throws Exception{
    Class<BottomNavigationView> bottomNavigationViewClass = BottomNavigationView.class;
    Field menuViewField = bottomNavigationViewClass.getDeclaredField("menuView");
    menuViewField.setAccessible(true);
    Object menuView = menuViewField.get(menu);
Class<span class="token generics function"><span class="token punctuation">&lt;</span>BottomNavigationMenuView<span class="token punctuation">&gt;</span></span> bottomNavigationMenuViewClass <span class="token operator">=</span> BottomNavigationMenuView<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">;</span>
Field buttonsField <span class="token operator">=</span> bottomNavigationMenuViewClass<span class="token punctuation">.</span><span class="token function">getDeclaredField</span><span class="token punctuation">(</span><span class="token string">"buttons"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
buttonsField<span class="token punctuation">.</span><span class="token function">setAccessible</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Object<span class="token punctuation">[</span><span class="token punctuation">]</span> buttons <span class="token operator">=</span> <span class="token punctuation">(</span>Object<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> buttonsField<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>menuView<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">for</span> <span class="token punctuation">(</span>Object button <span class="token operator">:</span> buttons<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    Class<span class="token generics function"><span class="token punctuation">&lt;</span>BottomNavigationItemView<span class="token punctuation">&gt;</span></span> bottomNavigationItemViewClass <span class="token operator">=</span> BottomNavigationItemView<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">;</span>
    Field smallLabelField <span class="token operator">=</span> bottomNavigationItemViewClass<span class="token punctuation">.</span><span class="token function">getDeclaredField</span><span class="token punctuation">(</span><span class="token string">"smallLabel"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    smallLabelField<span class="token punctuation">.</span><span class="token function">setAccessible</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    TextView smallLabel <span class="token operator">=</span> <span class="token punctuation">(</span>TextView<span class="token punctuation">)</span> smallLabelField<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>button<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">// 方式一:</span>

// ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) ((ViewGroup) smallLabel.getParent()).getLayoutParams();
// layoutParams.bottomMargin = -15;
// ((ViewGroup) smallLabel.getParent()).setLayoutParams(layoutParams);
// 方式二:
((ViewGroup) smallLabel.getParent()).scrollBy(0,-15);
}
}

  • 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

​ 效果如下:
在这里插入图片描述

8,修改控件高度

BottomNavigationView的默认高度是56dp,如果遇到操蛋的需求非要改它的话就覆盖一下design_bottom_navigation_height吧,如下:

<dimen name="design_bottom_navigation_height">84dp</dimen>

 
 
 
 
  • 1

四,结语

​ 关于BottomNavigationView可能用到的知识点就这些了,如果你还有还有什么奇葩的需求,那就去**“look the fuck resource code”** 吧

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于BottomNavigationView的使用姿势都在这里了 的相关文章

随机推荐

  • dfs and bfs template

    在做题的时候发现别人的模板后 再加上自己的理解 形成的更适合自己的模板 相当于随笔 就是记录一下 不做排版 记忆方法 树 BFS queue gt 马的遍历 NOTICE bfs 最短路 DFS stack 递归 gt 红细胞数 BFS t
  • 真香!值得收藏的30道Python练手题(附详细答案)

    大家好 今天给大家分享30道 Python 练习题 建议大家先独立思考一下解题思路 喜欢本文点赞支持 文末提供技术交流群 1 已知一个字符串为 hello world yoyo 如何得到一个队列 使用 split 函数 分割字符串 并且将数
  • 图像分割___图像分割方法综述

    From 变分方法与模糊聚类在图像分割中的应用研究 这里主要简单介绍几类经典的方法 基于边缘检测的方法 基于边缘检测的方法主要是通过检测出区域的边缘来进行分割 利用区域之间特征的不一致性 首先检测图像中的边缘点 然后按一定策略连接成闭合的曲
  • C++自学记录(const限定符)

    目录 const限定符 初始化和 const 默认状态下 const对象仅在文件内有效 const的引用 初始化和对const的引用 对const的引用可能引用一个并非const的对象 指针和const const指针 关于常量指针和指针常
  • C++虚函数的作用和实现原理

    一 什么是虚函数 在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数 用法格式为 virtual 函数返回类型 函数名 参数表 函数体 实现多态性 通过指向派生类的基类指针或引用 访问派生类中同名覆盖成员函数 二
  • 【Linux内核设计与实现】Linux内核简介

    之前在读 APUE 的时候 更多的是从上层去了解如何使用Linux系统的API 那个时候就十分喜欢Linux的设计 觉得一切都很奇妙 最近有些迷茫 不知道自己以后更加具体的技术方向在哪 所以最近广泛阅读了很多方面的书 C 方面 服务端网络编
  • ‘jmeter‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

    C Users wtcai gt jmeter jmeter 不是内部或外部命令 也不是可运行的程序 或批处理文件 一般该现象产生的原因是没有配置环境变量 找到此电脑 点击鼠标右键 找到属性 点击鼠标左键 点击右侧的 高级系统设置 然后点击
  • 【机器学习入门】决策树算法(四):CART算法(Classification and Regression Tree)

    CART算法的简介 CART Classification and Regression Tree 算法 即分类回归树算法 也是决策树构建的一种常用算法 CART的构建过程采用的是二分循环分割的方法 每次划分都把当前样本集划分为两个子样本集
  • Git的下载和安装【详细】

    目录 一 前言 二 准备工作 三 安装 无特殊需求可只看第五步一路next即可 lt 1 gt 开始安装 lt 2 gt 选择安装目录 lt 3 gt 选择安装组件 lt 4 gt 选择开始菜单文件夹 lt 5 gt 选择 Git 默认编辑
  • 计算机毕业设计SSM电影推荐系统【附源码数据库】

    项目运行 环境配置 Jdk1 8 Tomcat7 0 Mysql HBuilderX Webstorm也行 Eclispe IntelliJ IDEA Eclispe MyEclispe Sts都支持 项目技术 SSM mybatis Ma
  • 【 linux系统入门管理篇-第三章权限管理】

    linux系统入门管理篇 第三章权限管理 本章介绍 一 基本权限UGO 二 基本权限 ACL 三 特殊权限 本章介绍 本章讲述了 Linux系统CentOS7中关于权限的相关概念 以及用户和组的管理方法 一 基本权限UGO 概述 假如你想设
  • anaconda3/lib/python3.6/site-packages/torch/lib/libtorch_python.so: undefined symbol: PySlice_Unpack

    集群上运行pytorch代码 运行时候发现报错 anaconda3 lib python3 6 sitepackages torch lib libtorch python so undefined symbol PySlice Unpac
  • spring-aop的切入表达式和JoinPoint的使用以及怎么返回通知获取结果和在异常通知中获取异常还有环绕通知

    前言 本篇的Spring AOP系类文章第四篇讲解了spring aop的切入不表达式和JoinPoint的使用以及返回通知获取结果和异常通知中获取异常还有环绕通知 个人主页 尘觉主页 个人简介 大家好 我是尘觉 希望我的文章可以帮助到大家
  • 实验16:20211219 Java大数据1+X 中级实操考试(id:2846)

    实验16 20211219 Java大数据1 X 中级实操考试 id 2846 一 项目背景说明 二 表结构 三 步骤 5 分 步骤 1 项目准备 5 分 步骤 2 完成实体类 Student 10 分 步骤 3 完成实体类 Course
  • Nginx + tomcat 的搭建

    目录 一 硬件需求 二 nginx服务安装 1 系统初始化 2 安装环境 3 创建用户 4 解压 编译 安装 5 优化环境变量 6 配置nginx service文件 7 给与权限 三 tomcat 安装 两台安装一样 1 系统初始化 2
  • TT time tunnel时空隧道命令使用场景

    场景1 记录请求时间和次数 生产环境一定要加 n 参数 不然会打满jvm arthas 8868 tt t org fyh arthas controller ProgressController test n 5 Press Q or C
  • 电脑等保测评考证

    等保测评师是什么 公安部对等级测评工作 等级测评机构建设以及等级测评人员进行了规范和需求 需求开展等级测评的人员参加专门培训和考试 并取得 信息安全等级测评师证书 等级测评师分为初级 中级和高级 考试对象 信息安全等级保护测评师培训及考试对
  • centos下完全卸载mysql

    yum方式安装的mysql 1 yum remove mysql mysql server mysql libs compat mysql51 2 rm rf var lib mysql 3 rm etc my cnf 查看是否还有mysq
  • android studio 项目app红叉问题

    在导入项目 或者更新完项目的时候 这里会出现红叉 找寻原因 点击app旁边的箭头 点击上面圈出的地方 进入界面并能看到红字上显示了原因 寻找不到sdk 说明是在我们导入项目的时候sdk配置丢失了 解决方法 点击出sdk下载的界面 并且点击e
  • 关于BottomNavigationView的使用姿势都在这里了

    一 基本用法 1 首先需要添加依赖 implementation com google android material material 1 1 0 2 布局文件中引入