如何更改特定底部栏导航项的大小和形状
How to change the size and shape of a particular bottom bar navigation item
我正在尝试实现这个底部栏,其中包含一个比其他项目更大、形状不同的项目。
是否有使用本机底部导航组件实现此目的的简单方法?我猜不是,因为它似乎不符合 Material 设计规范。
否则,最好的方法是什么?我只看到 2 种方法可以实现此目的,但 none 对我来说似乎是可靠的。
- 对于每个 "small item",在可绘制对象的顶部添加一个透明条以达到相机图标的大小。
- 实现一个 5 项底部栏,中间有一个 "ghost item",我可以在其顶部放置一些其他组件。这将需要此组件与底部栏耦合。
编辑
这是我按照 Harshit 和 fmaccaroni 的建议通过增加图标大小获得的结果。
未选择项目时:
当项目被选中时:
亲:图标比其他的大
缺点:它仍然包含在底栏中。此外,它在选择时不垂直居中
可以通过
以编程方式更改底部栏导航中的图标大小
BottomNavigationView bottomNavigationView = (BottomNavigationView)
activity.findViewById(R.id.bottom_navigation_view);
BottomNavigationMenuView menuView = (BottomNavigationMenuView)
bottomNavigationView.getChildAt(0);
for (int i = 0; i < menuView.getChildCount(); i++) {
final View iconView =
menuView.getChildAt(i).findViewById(android.support.design.R.id.icon);
final ViewGroup.LayoutParams layoutParams = iconView.getLayoutParams();
final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
// set your height here
layoutParams.height = (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, displayMetrics);
// set your width here
layoutParams.width = (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, displayMetrics);
iconView.setLayoutParams(layoutParams);
}
我做了类似的事情来根据需要更改底部栏导航项的大小。
您可以执行以下操作:
为您希望在单击时显示更大尺寸的同一图像拍摄一张大尺寸图像,并将其存储在该可绘制文件夹中。
当单击特定项目的导航底部栏而不是将前一个较小的图像设置为较大的图像时应用。
你可以看看 this library 使用这个库来解决你的问题。
以 this 为参考,您可以迭代 BottomNavigationView 的每个子项并更改指定项目的大小:
BottomNavigationView bottomNavigationView = (BottomNavigationView) activity.findViewById(R.id.bottom_navigation_view);
BottomNavigationMenuView menuView = (BottomNavigationMenuView) bottomNavigationView.getChildAt(0);
for (int i = 0; i < menuView.getChildCount(); i++) {
final View iconView = menuView.getChildAt(i).findViewById(android.support.design.R.id.icon);
final ViewGroup.LayoutParams layoutParams = iconView.getLayoutParams();
final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
// If it is my special menu item change the size, otherwise take other size
if (i == 2){
// set your height here
layoutParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, displayMetrics);
// set your width here
layoutParams.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, displayMetrics);
}
else {
// set your height here
layoutParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, displayMetrics);
// set your width here
layoutParams.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, displayMetrics);
}
iconView.setLayoutParams(layoutParams);
}
经过一些研究,我发现 this library. They did not provide what I was looking for, but they implemented this behavior 在他们的一个样本中,这非常接近我需要的。
这是我通过重用他们的想法得到的(仅在 API 23 上测试过):
<blockquote class="imgur-embed-pub" lang="en" data-id="a/0Oypk"><a href="//imgur.com/0Oypk"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
它看起来不错,但我不喜欢这个实现,因为底部导航现在分为两个部分。
想法是在底栏中间创建一个空项目,并在其顶部添加一个浮动操作按钮,以营造它是底栏一部分的错觉。
这是我的底栏和浮动导航按钮的布局:
<com.ittianyu.bottomnavigationviewex.BottomNavigationViewEx
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="bottom"
app:elevation="0dp"
app:itemIconTint="@drawable/menu_item_selector"
app:itemTextColor="@drawable/menu_item_selector"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="@menu/navigation_items" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:focusable="true"
app:backgroundTint="@color/white"
app:borderWidth="0dp"
app:elevation="0dp"
app:fabSize="mini"
app:layout_constraintBottom_toBottomOf="@id/navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/camera_icon" />
导航栏项目:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/action_around_me"
android:icon="@drawable/ic_bottombar_around_me"
tools:ignore="MenuTitle" />
<item
android:id="@+id/action_my_projects"
android:icon="@drawable/ic_bottombar_projects"
tools:ignore="MenuTitle" />
<!-- Here is the trick -->
<item
android:id="@+id/empty"
android:enabled="false"
tools:ignore="MenuTitle" />
<item
android:id="@+id/action_notifications"
android:icon="@drawable/ic_bottombar_notification"
tools:ignore="MenuTitle" />
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_bottombar_settings"
tools:ignore="MenuTitle" />
</menu>
每次单击 FAB 按钮时,我都会禁用底部栏:
private void disableBottomBar() {
Menu menu = navigationBar.getMenu();
for (int i = 0; i < menu.size(); i++) {
// The third item is a an empty item so we do not do anything on it
if (i != 2) {
menu.getItem(i).setCheckable(false);
}
}
}
单击底部栏图标时 setCheckable(true)
的情况相同。
希望对您有所帮助。
自上次 Material 更新(2018 年)以来,可以使用本机 UI 元素执行此操作:
BottomAppBar
具有 app:fabAttached
属性
FloatingActionButton
与 app:layout_anchor
相关的 BottomAppBar
- 享受与
app:fabAlignmentMode
的对齐
您可以与 this great Medium article 联系以获取更多新的 material 元素以及有关此元素的更多详细信息。
希望对您有所帮助!
简单的方法是使用 setScaleX 和 setScaleY。例如:
final View iconView =
menuView.getChildAt(2).findViewById(android.support.design.R.id.icon);
iconView.setScaleY(1.5f);
iconView.setScaleX(1.5f);
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_alignParentBottom="true"
android:background="?android:attr/windowBackground"
app:itemIconTint="@color/colorPrimary"
app:itemTextColor="@android:color/black"
app:menu="@menu/navigation"
android:clipChildren="false">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="center"
android:layout_marginBottom="8dp"
app:elevation="6dp"
android:scaleType="center" />
</android.support.design.widget.BottomNavigationView>
同时将 android:clipChildren="false" 添加到根布局
我使用框架布局实现了相同的 UI。这是代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph_home" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_white_rounded_top"
app:itemTextColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="@menu/bottom_nav_bar_home_items"
app:labelVisibilityMode="unlabeled">
</com.google.android.material.bottomnavigation.BottomNavigationView>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<ImageView
android:id="@+id/toggle_alignment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_home_scan" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
并且不为中间项提供图标。
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="@+id/firstFragment"
android:icon="@drawable/ic_one"
android:title="" />
<item
android:id="@+id/secondFragment"
android:icon="@drawable/ic_two"
android:title="" />
<item
android:id="@+id/thirdFragment"
android:title="" />
<item
android:id="@+id/fourthFragment"
android:icon="@drawable/ic_four"
android:title=""/>
<item
android:id="@+id/fifthFragment"
android:icon="@drawable/ic_five"
android:title="" />
</group>
</menu>
对于 Androidx BottomNavigationView
遍历每个 child 并使用 'setIconSize()' 方法更改图标大小(考虑 @SuppressLint("RestrictedApi"))
val menuView: BottomNavigationMenuView = bottomNavigationView.getChildAt(0) as BottomNavigationMenuView
for (i in 0 until menuView.childCount) {
if (i == 3) {
val displayMetrics: DisplayMetrics = resources.displayMetrics
(menuView.getChildAt(i) as NavigationBarItemView).setIconSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 41f, displayMetrics).toInt())
}
}
我正在尝试实现这个底部栏,其中包含一个比其他项目更大、形状不同的项目。
是否有使用本机底部导航组件实现此目的的简单方法?我猜不是,因为它似乎不符合 Material 设计规范。
否则,最好的方法是什么?我只看到 2 种方法可以实现此目的,但 none 对我来说似乎是可靠的。
- 对于每个 "small item",在可绘制对象的顶部添加一个透明条以达到相机图标的大小。
- 实现一个 5 项底部栏,中间有一个 "ghost item",我可以在其顶部放置一些其他组件。这将需要此组件与底部栏耦合。
编辑
这是我按照 Harshit 和 fmaccaroni 的建议通过增加图标大小获得的结果。
未选择项目时:
当项目被选中时:
亲:图标比其他的大
缺点:它仍然包含在底栏中。此外,它在选择时不垂直居中
可以通过
以编程方式更改底部栏导航中的图标大小BottomNavigationView bottomNavigationView = (BottomNavigationView)
activity.findViewById(R.id.bottom_navigation_view);
BottomNavigationMenuView menuView = (BottomNavigationMenuView)
bottomNavigationView.getChildAt(0);
for (int i = 0; i < menuView.getChildCount(); i++) {
final View iconView =
menuView.getChildAt(i).findViewById(android.support.design.R.id.icon);
final ViewGroup.LayoutParams layoutParams = iconView.getLayoutParams();
final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
// set your height here
layoutParams.height = (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, displayMetrics);
// set your width here
layoutParams.width = (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, displayMetrics);
iconView.setLayoutParams(layoutParams);
}
我做了类似的事情来根据需要更改底部栏导航项的大小。
您可以执行以下操作:
为您希望在单击时显示更大尺寸的同一图像拍摄一张大尺寸图像,并将其存储在该可绘制文件夹中。
当单击特定项目的导航底部栏而不是将前一个较小的图像设置为较大的图像时应用。
你可以看看 this library 使用这个库来解决你的问题。
以 this 为参考,您可以迭代 BottomNavigationView 的每个子项并更改指定项目的大小:
BottomNavigationView bottomNavigationView = (BottomNavigationView) activity.findViewById(R.id.bottom_navigation_view);
BottomNavigationMenuView menuView = (BottomNavigationMenuView) bottomNavigationView.getChildAt(0);
for (int i = 0; i < menuView.getChildCount(); i++) {
final View iconView = menuView.getChildAt(i).findViewById(android.support.design.R.id.icon);
final ViewGroup.LayoutParams layoutParams = iconView.getLayoutParams();
final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
// If it is my special menu item change the size, otherwise take other size
if (i == 2){
// set your height here
layoutParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, displayMetrics);
// set your width here
layoutParams.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, displayMetrics);
}
else {
// set your height here
layoutParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, displayMetrics);
// set your width here
layoutParams.width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32, displayMetrics);
}
iconView.setLayoutParams(layoutParams);
}
经过一些研究,我发现 this library. They did not provide what I was looking for, but they implemented this behavior 在他们的一个样本中,这非常接近我需要的。
这是我通过重用他们的想法得到的(仅在 API 23 上测试过):
<blockquote class="imgur-embed-pub" lang="en" data-id="a/0Oypk"><a href="//imgur.com/0Oypk"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
它看起来不错,但我不喜欢这个实现,因为底部导航现在分为两个部分。
想法是在底栏中间创建一个空项目,并在其顶部添加一个浮动操作按钮,以营造它是底栏一部分的错觉。
这是我的底栏和浮动导航按钮的布局:
<com.ittianyu.bottomnavigationviewex.BottomNavigationViewEx
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="bottom"
app:elevation="0dp"
app:itemIconTint="@drawable/menu_item_selector"
app:itemTextColor="@drawable/menu_item_selector"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="@menu/navigation_items" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:focusable="true"
app:backgroundTint="@color/white"
app:borderWidth="0dp"
app:elevation="0dp"
app:fabSize="mini"
app:layout_constraintBottom_toBottomOf="@id/navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/camera_icon" />
导航栏项目:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/action_around_me"
android:icon="@drawable/ic_bottombar_around_me"
tools:ignore="MenuTitle" />
<item
android:id="@+id/action_my_projects"
android:icon="@drawable/ic_bottombar_projects"
tools:ignore="MenuTitle" />
<!-- Here is the trick -->
<item
android:id="@+id/empty"
android:enabled="false"
tools:ignore="MenuTitle" />
<item
android:id="@+id/action_notifications"
android:icon="@drawable/ic_bottombar_notification"
tools:ignore="MenuTitle" />
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_bottombar_settings"
tools:ignore="MenuTitle" />
</menu>
每次单击 FAB 按钮时,我都会禁用底部栏:
private void disableBottomBar() {
Menu menu = navigationBar.getMenu();
for (int i = 0; i < menu.size(); i++) {
// The third item is a an empty item so we do not do anything on it
if (i != 2) {
menu.getItem(i).setCheckable(false);
}
}
}
单击底部栏图标时 setCheckable(true)
的情况相同。
希望对您有所帮助。
自上次 Material 更新(2018 年)以来,可以使用本机 UI 元素执行此操作:
BottomAppBar
具有app:fabAttached
属性FloatingActionButton
与app:layout_anchor
相关的 BottomAppBar- 享受与
app:fabAlignmentMode
的对齐
您可以与 this great Medium article 联系以获取更多新的 material 元素以及有关此元素的更多详细信息。
希望对您有所帮助!
简单的方法是使用 setScaleX 和 setScaleY。例如:
final View iconView =
menuView.getChildAt(2).findViewById(android.support.design.R.id.icon);
iconView.setScaleY(1.5f);
iconView.setScaleX(1.5f);
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_alignParentBottom="true"
android:background="?android:attr/windowBackground"
app:itemIconTint="@color/colorPrimary"
app:itemTextColor="@android:color/black"
app:menu="@menu/navigation"
android:clipChildren="false">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="center"
android:layout_marginBottom="8dp"
app:elevation="6dp"
android:scaleType="center" />
</android.support.design.widget.BottomNavigationView>
同时将 android:clipChildren="false" 添加到根布局
我使用框架布局实现了相同的 UI。这是代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph_home" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/background_white_rounded_top"
app:itemTextColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="@menu/bottom_nav_bar_home_items"
app:labelVisibilityMode="unlabeled">
</com.google.android.material.bottomnavigation.BottomNavigationView>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<ImageView
android:id="@+id/toggle_alignment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_home_scan" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
并且不为中间项提供图标。
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="@+id/firstFragment"
android:icon="@drawable/ic_one"
android:title="" />
<item
android:id="@+id/secondFragment"
android:icon="@drawable/ic_two"
android:title="" />
<item
android:id="@+id/thirdFragment"
android:title="" />
<item
android:id="@+id/fourthFragment"
android:icon="@drawable/ic_four"
android:title=""/>
<item
android:id="@+id/fifthFragment"
android:icon="@drawable/ic_five"
android:title="" />
</group>
</menu>
对于 Androidx BottomNavigationView
遍历每个 child 并使用 'setIconSize()' 方法更改图标大小(考虑 @SuppressLint("RestrictedApi"))
val menuView: BottomNavigationMenuView = bottomNavigationView.getChildAt(0) as BottomNavigationMenuView
for (i in 0 until menuView.childCount) {
if (i == 3) {
val displayMetrics: DisplayMetrics = resources.displayMetrics
(menuView.getChildAt(i) as NavigationBarItemView).setIconSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 41f, displayMetrics).toInt())
}
}