如何在高于默认值的 BottomNavigationView 上添加指示器?
How to add indicator on a taller-than-default BottomNavigationView?
背景
我试图让 BottomNavigationView 大一点(高度大一点),同时让每个项目图标都有一个顶部指示器,表明它已被选中。
类似的东西,但高度更大:
在屏幕截图上很难看到它,但指示器显示在 BottomNavigationView 项目的最顶部,就在 BottomNavigationView 的阴影下方。
问题
当我设置较大的高度时,我得到的每个项目仍然采用较小的高度,因此指示器不会看顶部:
不仅如此,因为我之前itemBackground
设置了每个项目的背景都有指标,所以现在没有点击效果的背景了。
我发现了什么
关于身高,我发现,改变了身高。唯一的解决方案是覆盖库的尺寸。在这种情况下,只有这样:
<dimen name="design_bottom_navigation_height" tools:override="true">...</dimen>
但是,这仅解决了将指标放在顶部的问题。
此外,它看起来像一个肮脏的解决方案,为库强制设置维度,正如我所写的,因为我使用了 itemBackground
,它不再具有正常的点击效果。
这里是相关代码,仅根据 Android Studio 的向导进行了一些修改,用于制作 "Bottom Navigation Activity"。其余与那里相同:
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container" 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">
<TextView
android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin" android:text="@string/title_home"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view" android:layout_width="0dp"
android:layout_height="@dimen/tabs_height" android:layout_marginEnd="0dp"
android:layout_marginStart="0dp" android:background="?android:attr/windowBackground" app:itemBackground="@drawable/activity_main__tab_background"
app:labelVisibilityMode="unlabeled" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu"/>
</androidx.constraintlayout.widget.ConstraintLayout>
dimens.xml
<dimen name="tabs_height">64dp</dimen>
<dimen name="design_bottom_navigation_height" tools:override="true">@dimen/tabs_height</dimen>
activity_main__tab_background.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<layer-list>
<item android:gravity="top">
<shape android:shape="rectangle">
<size android:height="2dp"/>
<solid android:color="#07a5ea"/>
</shape>
</item>
</layer-list>
</item>
</selector>
问题
如何让指示器在顶部,同时拥有更大的 BottomNavigationView 并且不失去点击效果?
最好的解决方案是在运行时从 kotlin 代码更改项目 imageView 的边距
这是代码
private fun navigationImagesMargin(view: View) {
if (view is ViewGroup) {
for (i in 0 until view.childCount) {
val child = view.getChildAt(i)
navigationImagesMargin(child)
}
} else if (view is ImageView) {
val param = view.layoutParams as ViewGroup.MarginLayoutParams
param.topMargin = convertDpToPx(14)
view.layoutParams = param
}
}
fun convertDpToPx(dp: Int): Int {
return Math.round(dp * (resources.displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT))
}
在 onCreate 函数中调用 navigationImagesMargin
BottomNavigation View 上的函数
navigationImagesMargin(binding.spBottomNavigation)
但此解决方案需要在每次重新验证视图时调用 navigationImagesMargin
函数,即在 onItemClick 侦听器中,这里是
的代码
binding.spBottomNavigation.setOnNavigationItemSelectedListener { it->
binding.spBottomNavigation.post {
navigationImagesMargin(binding.spBottomNavigation)
}
true
}
这样一来,图像将保留在首次启动时您设定的位置
这是一个 link 包含完整代码的小型回购
https://github.com/abdulmalekDery/BottomNavigationControl
背景
我试图让 BottomNavigationView 大一点(高度大一点),同时让每个项目图标都有一个顶部指示器,表明它已被选中。
类似的东西,但高度更大:
在屏幕截图上很难看到它,但指示器显示在 BottomNavigationView 项目的最顶部,就在 BottomNavigationView 的阴影下方。
问题
当我设置较大的高度时,我得到的每个项目仍然采用较小的高度,因此指示器不会看顶部:
不仅如此,因为我之前itemBackground
设置了每个项目的背景都有指标,所以现在没有点击效果的背景了。
我发现了什么
关于身高,我发现
<dimen name="design_bottom_navigation_height" tools:override="true">...</dimen>
但是,这仅解决了将指标放在顶部的问题。
此外,它看起来像一个肮脏的解决方案,为库强制设置维度,正如我所写的,因为我使用了 itemBackground
,它不再具有正常的点击效果。
这里是相关代码,仅根据 Android Studio 的向导进行了一些修改,用于制作 "Bottom Navigation Activity"。其余与那里相同:
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container" 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">
<TextView
android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin" android:text="@string/title_home"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view" android:layout_width="0dp"
android:layout_height="@dimen/tabs_height" android:layout_marginEnd="0dp"
android:layout_marginStart="0dp" android:background="?android:attr/windowBackground" app:itemBackground="@drawable/activity_main__tab_background"
app:labelVisibilityMode="unlabeled" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu"/>
</androidx.constraintlayout.widget.ConstraintLayout>
dimens.xml
<dimen name="tabs_height">64dp</dimen>
<dimen name="design_bottom_navigation_height" tools:override="true">@dimen/tabs_height</dimen>
activity_main__tab_background.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<layer-list>
<item android:gravity="top">
<shape android:shape="rectangle">
<size android:height="2dp"/>
<solid android:color="#07a5ea"/>
</shape>
</item>
</layer-list>
</item>
</selector>
问题
如何让指示器在顶部,同时拥有更大的 BottomNavigationView 并且不失去点击效果?
最好的解决方案是在运行时从 kotlin 代码更改项目 imageView 的边距 这是代码
private fun navigationImagesMargin(view: View) {
if (view is ViewGroup) {
for (i in 0 until view.childCount) {
val child = view.getChildAt(i)
navigationImagesMargin(child)
}
} else if (view is ImageView) {
val param = view.layoutParams as ViewGroup.MarginLayoutParams
param.topMargin = convertDpToPx(14)
view.layoutParams = param
}
}
fun convertDpToPx(dp: Int): Int {
return Math.round(dp * (resources.displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT))
}
在 onCreate 函数中调用 navigationImagesMargin
BottomNavigation View 上的函数
navigationImagesMargin(binding.spBottomNavigation)
但此解决方案需要在每次重新验证视图时调用 navigationImagesMargin
函数,即在 onItemClick 侦听器中,这里是
binding.spBottomNavigation.setOnNavigationItemSelectedListener { it->
binding.spBottomNavigation.post {
navigationImagesMargin(binding.spBottomNavigation)
}
true
}
这样一来,图像将保留在首次启动时您设定的位置
这是一个 link 包含完整代码的小型回购 https://github.com/abdulmalekDery/BottomNavigationControl