在底部导航栏的图标顶部显示徽章

hei*_*g91 60 android material-design bottomnavigationview

我已经实现了我的应用程序底部的导航视图和我看过的每一个地方上的,如图标上方显示的徽章这个 我不知道这是否是甚至有可能实现.任何帮助表示赞赏.谢谢.

Tin*_*she 143

如果您只是想使用股票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);
Run Code Online (Sandbox Code Playgroud)

然后这是布局文件:

<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>
Run Code Online (Sandbox Code Playgroud)

然后只需TextView通过id和设置文本找到. @drawable/notification_badge只是一个圆形的可绘制的

  • 只需使用此方法删除徽章.`public void removeBadge(BottomNavigationView navigationView,int index){BottomNavigationMenuView bottomNavigationMenuView =(BottomNavigationMenuView)navigationView.getChildAt(0); 查看v = bottomNavigationMenuView.getChildAt(index); BottomNavigationItemView itemView =(BottomNavigationItemView)v; itemView.removeViewAt(itemView.getChildCount() - 1); }` (11认同)
  • 我有一个运行时异常:android.view.InflateException:二进制XML文件行#1:<merge />只能用于有效的ViewGroup根和attachToRoot = true (8认同)
  • 我想我发现了一种从@NileshRathore答案中删除徽章的更简洁的方法。我不是使用`itemView.removeViewAt(itemView.getChildCount()-1);`而是使用:`View badge = itemView.findViewById(R.id.notifications_badge); ((ViewGroup)badge.getParent())。removeView(badge);` (2认同)

Abe*_*bel 39

现在原生支持添加徽章,使用最新的材料依赖关系将其添加到build.gradle

    implementation 'com.google.android.material:material:1.1.0-alpha09'
Run Code Online (Sandbox Code Playgroud)

在您的布局中添加此

<!-- 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"
            />
Run Code Online (Sandbox Code Playgroud)

那你就可以

     val navBar  = findViewById<BottomNavigationView>(R.id.bottom_navigation)
     navBar.getOrCreateBadge(R.id.action_add).number = 2
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

  • 如果您的应用程序主题尚未像我一样继承 Theme.MaterialComponents (Theme.AppCompat),请准备对应用程序的其余部分进行一些重新设计。我应该先弄清楚这一点。顺便说一句,需要更改主题,否则徽章会崩溃。/sf/ask/3743328081/ (5认同)
  • 扩展我之前的评论,为了在从“Theme.AppCompat.*”变体迁移时保留样式,只需使用相应的“Theme.MaterialCompat.*.Bridge”变体进行直接翻译,而无需重新设计任何内容。https://medium.com/over-engineering/setting-up-a-material-components-theme-for-android-fbf7774da739 (4认同)
  • 恕我直言,答案应该更新为此。我只是在我的应用程序中实现了这一功能,并且就像一个魅力。 (2认同)

ilb*_*ose 31

我面临同样的问题,我不想使用图书馆.

所以我创建了一个自定义布局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>
Run Code Online (Sandbox Code Playgroud)

TextView背景(news_bottom_nav_bg):

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="?attr/colorPrimary" />
</shape>
Run Code Online (Sandbox Code Playgroud)

然后我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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后当我在我的活动中调用它时:

BottomMenuHelper.showBadge(this, mBottomNavigationView, R.id.action_news, "1");
Run Code Online (Sandbox Code Playgroud)

  • 在调用 `showBadge` 之前调用 `removeBadge` 以避免添加重复的视图。 (2认同)

Nom*_*que 30

使用支持库底部导航栏时,在菜单项上显示徽章/通知非常复杂.但是,有一些简单的解决方案可以完成它.例如 https://github.com/aurelhubert/ahbottomnavigation

此库是底部导航栏的更高级版本.您只需使用此代码段即可在菜单项上设置徽章.

bottomNavigation.setNotification(notification, bottomNavigation.getItemsCount() - 1);
Run Code Online (Sandbox Code Playgroud)

你会得到以下结果

在此输入图像描述


Mor*_*ard 15

BadgeDrawable 现在已将 Badge 添加为 AndroidX BottomNavigationView 的一部分。 查看文档

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>
Run Code Online (Sandbox Code Playgroud)

编辑:

正如评论中所指出的,应该可以只更新徽章计数,而无需像这样一直添加或删除徽章:

fun setBadge(count: Int) {
    bottomNavigationView.getBadge(menuItemId)?.isVisible = count > 0
}
Run Code Online (Sandbox Code Playgroud)


vuh*_*990 11

根据@ 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)
    }
Run Code Online (Sandbox Code Playgroud)

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" />
Run Code Online (Sandbox Code Playgroud)

和drawable background 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>
Run Code Online (Sandbox Code Playgroud)


Agi*_*ana 8

正如@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);
Run Code Online (Sandbox Code Playgroud)

来自我的要点


Aca*_*tta 7

一个简单的方法:

随着 Material Design 更新了他们的库,并根据

https://medium.com/over-engineering/hands-on-with-material-components-for-android-bottom-navigation-aae2aa9066be

我能够在没有任何外部 lib 的情况下从我的回收器适配器内部(在片段中)更新(或创建我的 BottomNavigationView Badge)。

初始状态: 初始状态

所以,就像在适配器中一样,我从我的活动中获得了上下文,我访问它并恢复底部导航的实例:

navBottomView = ((AppCompatActivity)this.context).findViewById(R.id.nav_view);
Run Code Online (Sandbox Code Playgroud)

检查徽章是否为空(尚未创建),如果是,则将其设置为所选数量:

  BadgeDrawable badgeDrawable = navBottomView.getBadge(R.id.navigation_carrinho);
  if (badgeDrawable == null)
      navBottomView.getOrCreateBadge(R.id.navigation_carrinho).setNumber(item.getQuantidade());
Run Code Online (Sandbox Code Playgroud)

否则获取之前的数量并增加徽章值:

int previousValue = badgeDrawable.getNumber();
badgeDrawable.setNumber(previousValue + item.getQuantidade());
Run Code Online (Sandbox Code Playgroud)

不要忘记导入:

import com.google.android.material.badge.BadgeDrawable;
import com.google.android.material.bottomnavigation.BottomNavigationView;
Run Code Online (Sandbox Code Playgroud)

最终状态:

最终状态

多合一添加到购物车按钮侦听器:

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());
            }
        });
Run Code Online (Sandbox Code Playgroud)


Sur*_*r D 5

请尝试一次。

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

3) 在您的活动 onCreate 方法中,将徽章视图添加到BottomNavigationView

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_landing);

         addBadgeView();

    }
Run Code Online (Sandbox Code Playgroud)

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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

注意: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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

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;
            }
        });
Run Code Online (Sandbox Code Playgroud)