在底部导航栏的图标顶部显示徽章
Display badge on top of bottom navigation bar's icon
我已经在我的应用程序中实现了底部导航视图,并且我已经查看了每个在图标顶部显示徽章的地方,例如 this
我想知道这是否有可能实施。任何帮助表示赞赏。
谢谢。
2020 年编辑:
Use BottomNavigation
from material components instead, it gives
support to add badges on items and many other features out of the box:
旧答案:
使用支持库底部导航栏时,在菜单项上显示 badge/notification 非常复杂。
但是,有一些简单的解决方案可以完成它。如
https://github.com/aurelhubert/ahbottomnavigation
这个库是底部导航栏的更高级版本。您只需使用此代码段即可在菜单项上设置徽章。
bottomNavigation.setNotification(notification, bottomNavigation.getItemsCount() - 1);
你会得到以下结果
使用支持库 BottomNavigationView 很困难。一个简单的解决方案是使用外部组件。
一个好办的是:https://github.com/roughike/BottomBar
查看它的文档很简单:
BottomBarTab nearby = bottomBar.getTabWithId(R.id.tab_nearby);
nearby.setBadgeCount(5);
// Remove the badge when you're done with it.
nearby.removeBadge/();
作为@zxbin 的回答。你可以检查 BadgeView 并尝试下面的代码
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(this);
navigation.setSelectedItemId(R.id.navigation_store);
BottomNavigationMenuView bottomNavigationMenuView =
(BottomNavigationMenuView) navigation.getChildAt(0);
View v = bottomNavigationMenuView.getChildAt(4); // number of menu from left
new QBadgeView(this).bindTarget(v).setBadgeNumber(5);
来自 my gist
如果您只想使用股票 BottomNavigationView
而没有第三方库,我是这样做的:
BottomNavigationMenuView bottomNavigationMenuView =
(BottomNavigationMenuView) navigationView.getChildAt(0);
View v = bottomNavigationMenuView.getChildAt(3);
BottomNavigationItemView itemView = (BottomNavigationItemView) v;
View badge = LayoutInflater.from(this)
.inflate(R.layout.notification_badge, itemView, true);
然后是布局文件:
<merge 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">
<TextView
android:id="@+id/notifications.badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:background="@drawable/notification_badge"
android:gravity="center"
android:padding="3dp"
android:text="9+"
android:textColor="@color/white"
android:textSize="11sp" />
</merge>
然后通过id找到TextView
并设置文本即可。
@drawable/notification_badge
只是一个可绘制的圆形
你可以这样试试:
在BottomNavigationView里面放一个TextView用于计数(BottomNavigationView是一个FrameLayout):
<android.support.design.widget.BottomNavigationView android:id="@id/bottomMenu" style="@style/bottomMenu">
<TextView android:id="@id/bottomMenuSelectionsNumber" style="@style/bottomMenuSelectionsNumber"/>
</android.support.design.widget.BottomNavigationView>
并像这样设计它们:
<style name="bottomMenu">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/toolbarHeight</item>
<item name="android:layout_gravity">center|bottom</item>
<item name="android:background">@color/colorThird</item>
<item name="itemBackground">@drawable/tabs_ripple</item>
<item name="itemIconTint">@drawable/bottom_menu_item_color</item>
<item name="itemTextColor">@drawable/bottom_menu_item_color</item>
<item name="menu">@menu/bottom_menu</item>
</style>
<style name="bottomMenuSelectionsNumber">
<item name="android:text">@string/bottomMenuSelectionsNumber</item>
<item name="android:textSize">@dimen/appSecondFontSize</item>
<item name="android:textColor">@color/white</item>
<item name="android:layout_width">@dimen/bottomMenuSelectionsNumberDim</item>
<item name="android:layout_height">@dimen/bottomMenuSelectionsNumberDim</item>
<item name="android:layout_gravity">right|bottom</item>
<item name="android:layout_marginRight">@dimen/bottomMenuSelectionsNumberMarginR</item>
<item name="android:layout_marginBottom">@dimen/bottomMenuSelectionsNumberMarginB</item>
<item name="android:gravity">center</item>
<item name="android:includeFontPadding">false</item>
<item name="android:background">@drawable/bottom_menu_selections_number_bg</item>
</style>
和bottom_menu_selections_number_bg:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/colorAccent"/>
<corners android:radius="@dimen/cornerRadius"/>
</shape>
更新:现在 material 支持徽章,详情见下文
val badge = bottomNavigation.getOrCreateBadge(menuItemId)
badge.isVisible = true
// An icon only badge will be displayed unless a number is set:
badge.number = 99
旧答案
根据@Tinashe 的回答,我希望徽章显示为没有数字的波纹管:
代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
// position = 2
addBadge(POSITION_HISTORY)
}
/**
* add badge(notification dot) to bottom bar
* @param position to get badge container
*/
@SuppressLint("PrivateResource")
private fun addBadge(position: Int) {
// get badge container (parent)
val bottomMenu = navigation.getChildAt(0) as? BottomNavigationMenuView
val v = bottomMenu?.getChildAt(position) as? BottomNavigationItemView
// inflate badge from layout
badge = LayoutInflater.from(this)
.inflate(R.layout.badge_layout, bottomMenu, false)
// create badge layout parameter
val badgeLayout: FrameLayout.LayoutParams = FrameLayout.LayoutParams(badge?.layoutParams).apply {
gravity = Gravity.CENTER_HORIZONTAL
topMargin = resources.getDimension(R.dimen.design_bottom_navigation_margin).toInt()
// <dimen name="bagde_left_margin">8dp</dimen>
leftMargin = resources.getDimension(R.dimen.bagde_left_margin).toInt()
}
// add view to bottom bar with layout parameter
v?.addView(badge, badgeLayout)
}
badge_layout.xml (badge_size=12dp)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/badge_size"
android:layout_height="@dimen/badge_size"
android:background="@drawable/new_notification" />
和可绘制背景new_notification.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<corners android:radius="100dp"/>
<solid android:color="#F44336"/>
</shape>
编辑 2:
BottomNavigationView 现在支持本地显示徽章,如文档 here.
中所述
bottomNavigation.getOrCreateBadge(menuItemId)
我遇到了同样的问题,我不想使用图书馆。
所以我创建了一个名为 layout_news_badge
的自定义布局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/badge_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/badge_text_view"
android:layout_width="19dp"
android:layout_height="19dp"
android:textSize="11sp"
android:textColor="@android:color/white"
android:background="@drawable/news_bottom_nav_bg"
android:layout_gravity="top"
android:layout_marginTop="4dp"
android:layout_marginStart="16dp"
android:gravity="center"
android:padding="2dp"
tools:text="9+" />
</FrameLayout>
TextView 背景(news_bottom_nav_bg
):
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="?attr/colorPrimary" />
</shape>
然后我用这两种方法创建了一个 BottomMenuHelper
:
public static void showBadge(Context context, BottomNavigationView
bottomNavigationView, @IdRes int itemId, String value) {
removeBadge(bottomNavigationView, itemId);
BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
View badge = LayoutInflater.from(context).inflate(R.layout.layout_news_badge, bottomNavigationView, false);
TextView text = badge.findViewById(R.id.badge_text_view);
text.setText(value);
itemView.addView(badge);
}
public static void removeBadge(BottomNavigationView bottomNavigationView, @IdRes int itemId) {
BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
if (itemView.getChildCount() == 3) {
itemView.removeViewAt(2);
}
}
然后当我在 Activity 中调用它时:
BottomMenuHelper.showBadge(this, mBottomNavigationView, R.id.action_news, "1");
编辑 1:
根据建议添加了改进 jatin rana
现在原生支持添加徽章,使用最新的 material 依赖
将此添加到您的 build.gradle
implementation 'com.google.android.material:material:1.1.0-alpha09'
在您的布局中添加这个
<!-- The rest of your layout here ....-->
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:menu="@menu/bottom_nav_menu"
/>
那你就可以
val navBar = findViewById<BottomNavigationView>(R.id.bottom_navigation)
navBar.getOrCreateBadge(R.id.action_add).number = 2
R.id.action_add 对您来说,就是您要在其上放置徽章的菜单项的 ID。从您提供给 BottomNavigationView 的菜单文件中检查它。
确保您的应用主题在 Theme.MaterialComponents
您可以在样式或清单中查看。
对于这个例子,我的是这个
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:statusBarColor" tools:targetApi="lollipop">@color/colorPrimary</item>
</style>
BadgeDrawable 现已将徽章添加为 AndroidX BottomNavigationView 的一部分。
See docs
fun setBadge(count: Int) {
if (count == 0) {
bottomNavigationView.removeBadge(R.id.ticketsNavigation)
} else {
val badge = bottomNavigationView.getOrCreateBadge(R.id.ticketsNavigation) // previously showBadge
badge.number = count
badge.backgroundColor = getColor(R.color.badge)
badge.badgeTextColor = getColor(R.color.blackTextColor)
}
}
// Menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/ticketsNavigation"
android:icon="@drawable/vector_drawable_navbar_tickets"
android:title="@string/tickets_title"/>
...
</menu>
编辑:
如评论中所述,应该可以只更新徽章计数,而无需像这样一直添加或删除徽章:
fun setBadge(count: Int) {
bottomNavigationView.getBadge(menuItemId)?.isVisible = count > 0
}
请试一次。
1) 为徽章创建 xml 文件(例如 notification_badge_view.xml)
<FrameLayout 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">
<ImageView
android:id="@+id/badge"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="top|center_horizontal"
android:layout_marginStart="10dp"
android:gravity="center"
android:padding="3dp"
app:srcCompat="@drawable/notification_badge" />
</FrameLayout>
2) 为通知点形状创建可绘制文件(例如 badge_circle.xml)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/colorAccent" />
<stroke
android:width="2dp"
android:color="@android:color/white" />
</shape>
3) 在您的 activity onCreate 方法中将徽章视图添加到 BottomNavigationView
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_landing);
addBadgeView();
}
4) 下面是addBadgeView方法
private void addBadgeView() {
try {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) bottomNavigationBar.getChildAt(0);
BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(0); //set this to 0, 1, 2, or 3.. accordingly which menu item of the bottom bar you want to show badge
notificationBadge = LayoutInflater.from(LandingActivity.this).inflate(R.layout.view_notification_badge, menuView, false);
itemView.addView(notificationBadge);
notificationBadge.setVisibility(GONE);// initially badge will be invisible
} catch (Exception e) {
e.printStackTrace();
}
}
注意:bottomNavigationBar 是您的底部栏视图。
5) 通过以下方法刷新徽章显示和隐藏
private void refreshBadgeView() {
try {
boolean badgeIsVisible = notificationBadge.getVisibility() != GONE;
notificationBadge.setVisibility(badgeIsVisible ? GONE : VISIBLE);//makes badge visible and invisible
} catch (Exception e) {
e.printStackTrace();
}
}
6) 当我们通过以下行点击特定的底部栏页面时,精细地隐藏。
bottomNavigationBar.setOnNavigationItemSelectedListener(new
BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem)
{
switch (menuItem.getItemId()) {
case R.id.bottom_bar_one:
//while moving to first fragment
notificationBadge.setVisibility(GONE);
break;
case R.id.bottom_bar_two:
//moving to second fragment
break;
case R.id.bottom_bar_three:
//moving to third fragment
break;
}
return true;
}
});
@Abel 的回答是最好的,除非您已经拥有一组复杂的主题并且没有时间更改它们。
但是,如果 a) 您时间紧迫并且您正在使用 Google Material 库 BottomNavigationView Bar 或 b) 您想要添加自己的自定义视图徽章 - 那么接受答案不适用于 com.google.android.material:material:1.1.0
您将需要为不同于已接受答案的视图层次结构编写代码
BottomNavigationItemView itemView = (BottomNavigationItemView) ((BottomNavigationMenuView) mBottomNavigation.getChildAt(0)).getChildAt(2);
View badge = LayoutInflater.from(this).inflate(R.layout.navigation_dot, itemView, false);
itemView.addView(badge);
如果你确实想更新你的主题并更新到
com.google.android.material:material:1.1.0-alpha09
那么您需要做的就是
mBottomNavigation.getOrCreateBadge(R.id.navigation_menu_item_one).setNumber(YOUR_NUMBER);
remove 和 number 函数仅存在于 1.1.0-alpha09 版本(及更高版本)中
查看文档页面:
https://material.io/develop/android/components/bottom-navigation-view/
TL;DR:
他们没有更新正确的使用方法,所以他们在文档上留下了一个小错误。要添加或删除徽章,请执行以下操作:
// to remove
bottomNavigationView.removeBadge(R.id.action_settings)
// to add
bottomNavigationView.getOrCreateBadge(R.id.action_settings).apply {
//if you want to change other attributes, like badge color, add a number, maximum number (a plus sign is added, e.g. 99+)
number = 100
maxCharactersCount = 3
backgroundColor = ContextCompat.getColor(context, R.color.color_red)
}
我以这种方式对@ilbose 的答案做了一些更改,并测试了小屏幕和大屏幕尺寸
../drawable/badge_circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/solid_red_base" />
和../layout/notifcation_badge.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/badge_frame_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="11dp"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/badge_text_view"
android:layout_width="12dp"
android:layout_height="12dp"
android:textSize="11sp"
android:textColor="@android:color/white"
android:background="@drawable/message_badge"
android:layout_gravity="top"
android:layout_centerHorizontal="true"
android:padding="2dp"/> </RelativeLayout>
并在 java 代码中
public static void showBadge(Context context, BottomNavigationView
bottomNavigationView, @IdRes int itemId, String value) {
BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
View badge = LayoutInflater.from(context).inflate(R.layout.message_notification_badge, bottomNavigationView, false);
TextView text = badge.findViewById(R.id.badge_text_view);
text.setText(value);
itemView.addView(badge);
}
public static void removeBadge(BottomNavigationView bottomNavigationView, @IdRes int itemId) {
BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
if (itemView.getChildCount() == 4) {
itemView.removeViewAt(4);
}
}
一个简单的方法:
作为 Material Design 更新了他们的库并根据
我能够从我的回收器适配器内部(在片段中)更新(或创建我的 BottomNavigationView 徽章)无需任何外部库。
初始状态:
因此,在适配器中,我从 activity 获取了上下文,我访问它并恢复底部导航的实例:
navBottomView = ((AppCompatActivity)this.context).findViewById(R.id.nav_view);
检查徽章是否为空(尚未创建),如果是,将其设置为所选数量:
BadgeDrawable badgeDrawable = navBottomView.getBadge(R.id.navigation_carrinho);
if (badgeDrawable == null)
navBottomView.getOrCreateBadge(R.id.navigation_carrinho).setNumber(item.getQuantidade());
否则获取之前的数量并增加徽章值:
int previousValue = badgeDrawable.getNumber();
badgeDrawable.setNumber(previousValue + item.getQuantidade());
不要忘记导入:
import com.google.android.material.badge.BadgeDrawable;
import com.google.android.material.bottomnavigation.BottomNavigationView;
最终状态:
带有添加到购物车按钮侦听器的一体机:
btnAddCarrinho.setOnClickListener(v -> {
navBottomView = ((AppCompatActivity) this.context).findViewById(R.id.nav_view);
BadgeDrawable badgeDrawable = navBottomView.getBadge(R.id.navigation_carrinho);
if (badgeDrawable == null) {
navBottomView.getOrCreateBadge(R.id.navigation_carrinho).setNumber(item.getQuantidade());
} else {
int previousValue = badgeDrawable.getNumber();
badgeDrawable.setNumber(previousValue + item.getQuantidade());
}
});
这是使用 material 底部导航创建和删除徽章计数的简单方法。
public class BadgeIconHelper {
public static void showNotificationBadge(BottomNavigationView
bottomNavigationView, @IdRes int itemId, String value) {
BadgeDrawable badge = bottomNavigationView.getOrCreateBadge(itemId);
badge.setBackgroundColor(ContextCompat.getColor(bottomNavigationView.getContext(), R.color.color_primary));
badge.setBadgeTextColor(ContextCompat.getColor(bottomNavigationView.getContext(), R.color.color_white));
badge.setMaxCharacterCount(3);
badge.setVerticalOffset(2);
badge.setVisible(true);
badge.setNumber(Integer.parseInt(value));
}
public static void removeNotificationBadge(BottomNavigationView bottomNavigationView, @IdRes int itemId) {
BadgeDrawable badgeDrawable = bottomNavigationView.getBadge(itemId);
if (badgeDrawable != null) {
badgeDrawable.setVisible(false);
badgeDrawable.clearNumber();
}
}
}
首先创建徽章的布局文件,然后按照以下步骤操作
BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigation.getChildAt(0);
BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(2);
View messageBadgeView = LayoutInflater.from(this).inflate(R.layout.message_badge_view, menuView, false);
TextView textView = messageBadgeView.findViewById(R.id.counter_badge);
textView.setText("15");
itemView.addView(messageBadgeView);`
如果您只想要没有数字的点,那么您可以使用 com.google.android.material.bottomnavigation.BottomNavigationView
创建底部导航
在 java
BottomNavigationView mBtmView = (BottomNavigationView) findViewById(R.id.bottom_navigatin_view);
mBtmView.setOnNavigationItemSelectedListener(this);
mBtmView.getOrCreateBadge(R.id.chatFragment).setBackgroundColor(getResources().getColor(R.color.Red));
我已经在我的应用程序中实现了底部导航视图,并且我已经查看了每个在图标顶部显示徽章的地方,例如 this 我想知道这是否有可能实施。任何帮助表示赞赏。 谢谢。
2020 年编辑:
Use
BottomNavigation
from material components instead, it gives support to add badges on items and many other features out of the box:
旧答案:
使用支持库底部导航栏时,在菜单项上显示 badge/notification 非常复杂。 但是,有一些简单的解决方案可以完成它。如 https://github.com/aurelhubert/ahbottomnavigation
这个库是底部导航栏的更高级版本。您只需使用此代码段即可在菜单项上设置徽章。
bottomNavigation.setNotification(notification, bottomNavigation.getItemsCount() - 1);
你会得到以下结果
使用支持库 BottomNavigationView 很困难。一个简单的解决方案是使用外部组件。 一个好办的是:https://github.com/roughike/BottomBar 查看它的文档很简单:
BottomBarTab nearby = bottomBar.getTabWithId(R.id.tab_nearby);
nearby.setBadgeCount(5);
// Remove the badge when you're done with it.
nearby.removeBadge/();
作为@zxbin 的回答。你可以检查 BadgeView 并尝试下面的代码
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(this);
navigation.setSelectedItemId(R.id.navigation_store);
BottomNavigationMenuView bottomNavigationMenuView =
(BottomNavigationMenuView) navigation.getChildAt(0);
View v = bottomNavigationMenuView.getChildAt(4); // number of menu from left
new QBadgeView(this).bindTarget(v).setBadgeNumber(5);
来自 my gist
如果您只想使用股票 BottomNavigationView
而没有第三方库,我是这样做的:
BottomNavigationMenuView bottomNavigationMenuView =
(BottomNavigationMenuView) navigationView.getChildAt(0);
View v = bottomNavigationMenuView.getChildAt(3);
BottomNavigationItemView itemView = (BottomNavigationItemView) v;
View badge = LayoutInflater.from(this)
.inflate(R.layout.notification_badge, itemView, true);
然后是布局文件:
<merge 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">
<TextView
android:id="@+id/notifications.badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:background="@drawable/notification_badge"
android:gravity="center"
android:padding="3dp"
android:text="9+"
android:textColor="@color/white"
android:textSize="11sp" />
</merge>
然后通过id找到TextView
并设置文本即可。
@drawable/notification_badge
只是一个可绘制的圆形
你可以这样试试:
在BottomNavigationView里面放一个TextView用于计数(BottomNavigationView是一个FrameLayout):
<android.support.design.widget.BottomNavigationView android:id="@id/bottomMenu" style="@style/bottomMenu">
<TextView android:id="@id/bottomMenuSelectionsNumber" style="@style/bottomMenuSelectionsNumber"/>
</android.support.design.widget.BottomNavigationView>
并像这样设计它们:
<style name="bottomMenu">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/toolbarHeight</item>
<item name="android:layout_gravity">center|bottom</item>
<item name="android:background">@color/colorThird</item>
<item name="itemBackground">@drawable/tabs_ripple</item>
<item name="itemIconTint">@drawable/bottom_menu_item_color</item>
<item name="itemTextColor">@drawable/bottom_menu_item_color</item>
<item name="menu">@menu/bottom_menu</item>
</style>
<style name="bottomMenuSelectionsNumber">
<item name="android:text">@string/bottomMenuSelectionsNumber</item>
<item name="android:textSize">@dimen/appSecondFontSize</item>
<item name="android:textColor">@color/white</item>
<item name="android:layout_width">@dimen/bottomMenuSelectionsNumberDim</item>
<item name="android:layout_height">@dimen/bottomMenuSelectionsNumberDim</item>
<item name="android:layout_gravity">right|bottom</item>
<item name="android:layout_marginRight">@dimen/bottomMenuSelectionsNumberMarginR</item>
<item name="android:layout_marginBottom">@dimen/bottomMenuSelectionsNumberMarginB</item>
<item name="android:gravity">center</item>
<item name="android:includeFontPadding">false</item>
<item name="android:background">@drawable/bottom_menu_selections_number_bg</item>
</style>
和bottom_menu_selections_number_bg:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/colorAccent"/>
<corners android:radius="@dimen/cornerRadius"/>
</shape>
更新:现在 material 支持徽章,详情见下文
val badge = bottomNavigation.getOrCreateBadge(menuItemId)
badge.isVisible = true
// An icon only badge will be displayed unless a number is set:
badge.number = 99
旧答案
根据@Tinashe 的回答,我希望徽章显示为没有数字的波纹管:
代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
// position = 2
addBadge(POSITION_HISTORY)
}
/**
* add badge(notification dot) to bottom bar
* @param position to get badge container
*/
@SuppressLint("PrivateResource")
private fun addBadge(position: Int) {
// get badge container (parent)
val bottomMenu = navigation.getChildAt(0) as? BottomNavigationMenuView
val v = bottomMenu?.getChildAt(position) as? BottomNavigationItemView
// inflate badge from layout
badge = LayoutInflater.from(this)
.inflate(R.layout.badge_layout, bottomMenu, false)
// create badge layout parameter
val badgeLayout: FrameLayout.LayoutParams = FrameLayout.LayoutParams(badge?.layoutParams).apply {
gravity = Gravity.CENTER_HORIZONTAL
topMargin = resources.getDimension(R.dimen.design_bottom_navigation_margin).toInt()
// <dimen name="bagde_left_margin">8dp</dimen>
leftMargin = resources.getDimension(R.dimen.bagde_left_margin).toInt()
}
// add view to bottom bar with layout parameter
v?.addView(badge, badgeLayout)
}
badge_layout.xml (badge_size=12dp)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/badge_size"
android:layout_height="@dimen/badge_size"
android:background="@drawable/new_notification" />
和可绘制背景new_notification.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<corners android:radius="100dp"/>
<solid android:color="#F44336"/>
</shape>
编辑 2:
BottomNavigationView 现在支持本地显示徽章,如文档 here.
bottomNavigation.getOrCreateBadge(menuItemId)
我遇到了同样的问题,我不想使用图书馆。
所以我创建了一个名为 layout_news_badge
的自定义布局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/badge_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/badge_text_view"
android:layout_width="19dp"
android:layout_height="19dp"
android:textSize="11sp"
android:textColor="@android:color/white"
android:background="@drawable/news_bottom_nav_bg"
android:layout_gravity="top"
android:layout_marginTop="4dp"
android:layout_marginStart="16dp"
android:gravity="center"
android:padding="2dp"
tools:text="9+" />
</FrameLayout>
TextView 背景(news_bottom_nav_bg
):
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="?attr/colorPrimary" />
</shape>
然后我用这两种方法创建了一个 BottomMenuHelper
:
public static void showBadge(Context context, BottomNavigationView
bottomNavigationView, @IdRes int itemId, String value) {
removeBadge(bottomNavigationView, itemId);
BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
View badge = LayoutInflater.from(context).inflate(R.layout.layout_news_badge, bottomNavigationView, false);
TextView text = badge.findViewById(R.id.badge_text_view);
text.setText(value);
itemView.addView(badge);
}
public static void removeBadge(BottomNavigationView bottomNavigationView, @IdRes int itemId) {
BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
if (itemView.getChildCount() == 3) {
itemView.removeViewAt(2);
}
}
然后当我在 Activity 中调用它时:
BottomMenuHelper.showBadge(this, mBottomNavigationView, R.id.action_news, "1");
编辑 1: 根据建议添加了改进 jatin rana
现在原生支持添加徽章,使用最新的 material 依赖 将此添加到您的 build.gradle
implementation 'com.google.android.material:material:1.1.0-alpha09'
在您的布局中添加这个
<!-- The rest of your layout here ....-->
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:menu="@menu/bottom_nav_menu"
/>
那你就可以
val navBar = findViewById<BottomNavigationView>(R.id.bottom_navigation)
navBar.getOrCreateBadge(R.id.action_add).number = 2
R.id.action_add 对您来说,就是您要在其上放置徽章的菜单项的 ID。从您提供给 BottomNavigationView 的菜单文件中检查它。
确保您的应用主题在 Theme.MaterialComponents
您可以在样式或清单中查看。 对于这个例子,我的是这个
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:statusBarColor" tools:targetApi="lollipop">@color/colorPrimary</item>
</style>
BadgeDrawable 现已将徽章添加为 AndroidX BottomNavigationView 的一部分。 See docs
fun setBadge(count: Int) {
if (count == 0) {
bottomNavigationView.removeBadge(R.id.ticketsNavigation)
} else {
val badge = bottomNavigationView.getOrCreateBadge(R.id.ticketsNavigation) // previously showBadge
badge.number = count
badge.backgroundColor = getColor(R.color.badge)
badge.badgeTextColor = getColor(R.color.blackTextColor)
}
}
// Menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/ticketsNavigation"
android:icon="@drawable/vector_drawable_navbar_tickets"
android:title="@string/tickets_title"/>
...
</menu>
编辑:
如评论中所述,应该可以只更新徽章计数,而无需像这样一直添加或删除徽章:
fun setBadge(count: Int) {
bottomNavigationView.getBadge(menuItemId)?.isVisible = count > 0
}
请试一次。
1) 为徽章创建 xml 文件(例如 notification_badge_view.xml)
<FrameLayout 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">
<ImageView
android:id="@+id/badge"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="top|center_horizontal"
android:layout_marginStart="10dp"
android:gravity="center"
android:padding="3dp"
app:srcCompat="@drawable/notification_badge" />
</FrameLayout>
2) 为通知点形状创建可绘制文件(例如 badge_circle.xml)
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/colorAccent" />
<stroke
android:width="2dp"
android:color="@android:color/white" />
</shape>
3) 在您的 activity onCreate 方法中将徽章视图添加到 BottomNavigationView
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_landing);
addBadgeView();
}
4) 下面是addBadgeView方法
private void addBadgeView() {
try {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) bottomNavigationBar.getChildAt(0);
BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(0); //set this to 0, 1, 2, or 3.. accordingly which menu item of the bottom bar you want to show badge
notificationBadge = LayoutInflater.from(LandingActivity.this).inflate(R.layout.view_notification_badge, menuView, false);
itemView.addView(notificationBadge);
notificationBadge.setVisibility(GONE);// initially badge will be invisible
} catch (Exception e) {
e.printStackTrace();
}
}
注意:bottomNavigationBar 是您的底部栏视图。
5) 通过以下方法刷新徽章显示和隐藏
private void refreshBadgeView() {
try {
boolean badgeIsVisible = notificationBadge.getVisibility() != GONE;
notificationBadge.setVisibility(badgeIsVisible ? GONE : VISIBLE);//makes badge visible and invisible
} catch (Exception e) {
e.printStackTrace();
}
}
6) 当我们通过以下行点击特定的底部栏页面时,精细地隐藏。
bottomNavigationBar.setOnNavigationItemSelectedListener(new
BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem)
{
switch (menuItem.getItemId()) {
case R.id.bottom_bar_one:
//while moving to first fragment
notificationBadge.setVisibility(GONE);
break;
case R.id.bottom_bar_two:
//moving to second fragment
break;
case R.id.bottom_bar_three:
//moving to third fragment
break;
}
return true;
}
});
@Abel 的回答是最好的,除非您已经拥有一组复杂的主题并且没有时间更改它们。
但是,如果 a) 您时间紧迫并且您正在使用 Google Material 库 BottomNavigationView Bar 或 b) 您想要添加自己的自定义视图徽章 - 那么接受答案不适用于 com.google.android.material:material:1.1.0
您将需要为不同于已接受答案的视图层次结构编写代码
BottomNavigationItemView itemView = (BottomNavigationItemView) ((BottomNavigationMenuView) mBottomNavigation.getChildAt(0)).getChildAt(2);
View badge = LayoutInflater.from(this).inflate(R.layout.navigation_dot, itemView, false);
itemView.addView(badge);
如果你确实想更新你的主题并更新到
com.google.android.material:material:1.1.0-alpha09
那么您需要做的就是
mBottomNavigation.getOrCreateBadge(R.id.navigation_menu_item_one).setNumber(YOUR_NUMBER);
remove 和 number 函数仅存在于 1.1.0-alpha09 版本(及更高版本)中
查看文档页面: https://material.io/develop/android/components/bottom-navigation-view/
TL;DR: 他们没有更新正确的使用方法,所以他们在文档上留下了一个小错误。要添加或删除徽章,请执行以下操作:
// to remove
bottomNavigationView.removeBadge(R.id.action_settings)
// to add
bottomNavigationView.getOrCreateBadge(R.id.action_settings).apply {
//if you want to change other attributes, like badge color, add a number, maximum number (a plus sign is added, e.g. 99+)
number = 100
maxCharactersCount = 3
backgroundColor = ContextCompat.getColor(context, R.color.color_red)
}
我以这种方式对@ilbose 的答案做了一些更改,并测试了小屏幕和大屏幕尺寸
../drawable/badge_circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/solid_red_base" />
和../layout/notifcation_badge.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/badge_frame_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="11dp"
android:layout_gravity="center_horizontal">
<TextView
android:id="@+id/badge_text_view"
android:layout_width="12dp"
android:layout_height="12dp"
android:textSize="11sp"
android:textColor="@android:color/white"
android:background="@drawable/message_badge"
android:layout_gravity="top"
android:layout_centerHorizontal="true"
android:padding="2dp"/> </RelativeLayout>
并在 java 代码中
public static void showBadge(Context context, BottomNavigationView
bottomNavigationView, @IdRes int itemId, String value) {
BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
View badge = LayoutInflater.from(context).inflate(R.layout.message_notification_badge, bottomNavigationView, false);
TextView text = badge.findViewById(R.id.badge_text_view);
text.setText(value);
itemView.addView(badge);
}
public static void removeBadge(BottomNavigationView bottomNavigationView, @IdRes int itemId) {
BottomNavigationItemView itemView = bottomNavigationView.findViewById(itemId);
if (itemView.getChildCount() == 4) {
itemView.removeViewAt(4);
}
}
一个简单的方法:
作为 Material Design 更新了他们的库并根据
我能够从我的回收器适配器内部(在片段中)更新(或创建我的 BottomNavigationView 徽章)无需任何外部库。
初始状态:
因此,在适配器中,我从 activity 获取了上下文,我访问它并恢复底部导航的实例:
navBottomView = ((AppCompatActivity)this.context).findViewById(R.id.nav_view);
检查徽章是否为空(尚未创建),如果是,将其设置为所选数量:
BadgeDrawable badgeDrawable = navBottomView.getBadge(R.id.navigation_carrinho);
if (badgeDrawable == null)
navBottomView.getOrCreateBadge(R.id.navigation_carrinho).setNumber(item.getQuantidade());
否则获取之前的数量并增加徽章值:
int previousValue = badgeDrawable.getNumber();
badgeDrawable.setNumber(previousValue + item.getQuantidade());
不要忘记导入:
import com.google.android.material.badge.BadgeDrawable;
import com.google.android.material.bottomnavigation.BottomNavigationView;
最终状态:
带有添加到购物车按钮侦听器的一体机:
btnAddCarrinho.setOnClickListener(v -> {
navBottomView = ((AppCompatActivity) this.context).findViewById(R.id.nav_view);
BadgeDrawable badgeDrawable = navBottomView.getBadge(R.id.navigation_carrinho);
if (badgeDrawable == null) {
navBottomView.getOrCreateBadge(R.id.navigation_carrinho).setNumber(item.getQuantidade());
} else {
int previousValue = badgeDrawable.getNumber();
badgeDrawable.setNumber(previousValue + item.getQuantidade());
}
});
这是使用 material 底部导航创建和删除徽章计数的简单方法。
public class BadgeIconHelper {
public static void showNotificationBadge(BottomNavigationView
bottomNavigationView, @IdRes int itemId, String value) {
BadgeDrawable badge = bottomNavigationView.getOrCreateBadge(itemId);
badge.setBackgroundColor(ContextCompat.getColor(bottomNavigationView.getContext(), R.color.color_primary));
badge.setBadgeTextColor(ContextCompat.getColor(bottomNavigationView.getContext(), R.color.color_white));
badge.setMaxCharacterCount(3);
badge.setVerticalOffset(2);
badge.setVisible(true);
badge.setNumber(Integer.parseInt(value));
}
public static void removeNotificationBadge(BottomNavigationView bottomNavigationView, @IdRes int itemId) {
BadgeDrawable badgeDrawable = bottomNavigationView.getBadge(itemId);
if (badgeDrawable != null) {
badgeDrawable.setVisible(false);
badgeDrawable.clearNumber();
}
}
}
首先创建徽章的布局文件,然后按照以下步骤操作
BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigation.getChildAt(0);
BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(2);
View messageBadgeView = LayoutInflater.from(this).inflate(R.layout.message_badge_view, menuView, false);
TextView textView = messageBadgeView.findViewById(R.id.counter_badge);
textView.setText("15");
itemView.addView(messageBadgeView);`
如果您只想要没有数字的点,那么您可以使用 com.google.android.material.bottomnavigation.BottomNavigationView
创建底部导航
在 java
BottomNavigationView mBtmView = (BottomNavigationView) findViewById(R.id.bottom_navigatin_view);
mBtmView.setOnNavigationItemSelectedListener(this);
mBtmView.getOrCreateBadge(R.id.chatFragment).setBackgroundColor(getResources().getColor(R.color.Red));