You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Toolbar带计数角标通知铃铛计数为0时点击无响应

问题现象

在Toolbar中实现带通知计数角标的通知铃铛图标时,非零计数场景功能运行符合预期,但通知计数为0时点击铃铛图标无法触发响应。初步推测问题与铃铛上层展示计数的actionLayout配置有关,但铃铛图标本身理论上应正常接收点击事件,暂未定位到代码异常位置。
已确认的现象:

  • 通知计数为0时,onMenuItemClick回调内的日志打印、Toast提示均不会执行
  • 通知计数非0时,计数角标的点击事件可正常触发
相关实现代码

菜单项配置

<item android:id="@+id/notificationBell"
    android:title=""
    android:icon="@drawable/notification"
    app:actionLayout="@layout/menuitem_notification_count"
    android:visible="true"
    app:showAsAction="always">
</item>

自定义Action布局(menuitem_notification_count.xml)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    style="?attr/actionButtonStyle"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clipToPadding="false"
    android:focusable="true">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/notification"/>

    <TextView
        android:id="@+id/cart_badge"
        android:layout_width="22dp"
        android:layout_height="22dp"
        android:layout_gravity="end|top"
        android:layout_marginEnd="-10dp"
        android:layout_marginTop="1dp"
        android:padding="2dp"
        android:background="@drawable/notification_count_background"
        android:textAlignment="center"
        android:gravity="center"
        android:textColor="@android:color/white"
        android:textSize="12sp"/>

</FrameLayout>

菜单初始化逻辑(onCreateOptionsMenu)

@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.menu_notification, menu);
    MenuItem notificationBell = menu.findItem(R.id.notificationBell);
    textNotificationCount = notificationBell.getActionView().findViewById(R.id.cart_badge);
    Typeface fontFace = ResourcesCompat.getFont(getActivity(), R.font.roboto_medium_numbers);
    textNotificationCount.setTypeface(fontFace);
    notificationCount = getNotificationCount();
    int checkCount = Integer.parseInt(notificationCount);
    Log.d(TAG, "run:  Notification Count = " + notificationCount);
    notificationBell.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem menuItem) {
            if (checkCount==0){
                // 此处Toast和日志始终无法触发
                Log.d(TAG, "run:  Notification Count Is 0");
                Toast.makeText(getActivity(), "No New Notifications.", Toast.LENGTH_SHORT).show();
            }

            return false;
        }
    });
    if (checkCount == 0) {
        if (textNotificationCount.getVisibility() != View.GONE) {
            textNotificationCount.setVisibility(View.GONE);
        }
    } else if (checkCount > 99) {
        textNotificationCount.setText("99+");
        if (textNotificationCount.getVisibility() != View.VISIBLE) {
            textNotificationCount.setVisibility(View.VISIBLE);
        }
    } else {
        textNotificationCount.setText(notificationCount);
        if (textNotificationCount.getVisibility() != View.VISIBLE) {
            textNotificationCount.setVisibility(View.VISIBLE);
        }
    }

    textNotificationCount.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // 计数非0时该点击事件可正常触发
        }
    });

}
问题根因

给MenuItem设置自定义actionLayout后,菜单项的点击事件分发会被自定义Action视图完全接管,外层的onMenuItemClick回调只有在Action视图及其子View都不消费点击事件时才会触发。
代码存在两个直接导致点击失效的问题:

  1. 自定义布局的根FrameLayout设置了android:focusable="true",同时继承了?attr/actionButtonStyle自带的可点击属性,会优先拦截整个菜单项区域的触摸事件,但没有给这个根布局设置点击监听,事件被它直接消费,根本不会传到外层的onMenuItemClick。
  2. 非零计数时只给角标TextView设置了点击监听,点角标能触发响应只是因为点到了绑定了监听的TextView,点铃铛图标本身其实也不会触发onMenuItemClick,只是之前测试非0场景时大概率点到了角标才误以为功能正常;计数为0时角标被设为GONE,整个可点击区域只剩未绑定监听的根布局和ImageView,点击后自然没有任何响应。
修复方案
  1. 删掉自定义Action布局根FrameLayout上多余的android:focusable="true"属性,避免不必要的焦点抢占。
  2. 不要依赖setOnMenuItemClickListener处理带自定义Action视图的菜单项点击,直接给Action视图的根布局绑定统一的点击监听,覆盖整个铃铛的点击区域,不管角标是否显示、点在铃铛哪个位置都能正常触发逻辑。
  3. 删掉之前单独给角标TextView设置的点击监听,点击角标时事件会自动冒泡到上层根布局,无需重复绑定。

核心修复代码参考:

@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.menu_notification, menu);
    MenuItem notificationBell = menu.findItem(R.id.notificationBell);
    // 先拿到自定义Action的根视图
    View actionRoot = notificationBell.getActionView();
    textNotificationCount = actionRoot.findViewById(R.id.cart_badge);
    
    // ... 省略原有字体设置、计数获取逻辑 ...

    // 给根视图绑定统一点击监听,覆盖整个铃铛区域
    actionRoot.setOnClickListener(v -> {
        if (checkCount == 0){
            Log.d(TAG, "run:  Notification Count Is 0");
            Toast.makeText(getActivity(), "No New Notifications.", Toast.LENGTH_SHORT).show();
        } else {
            // 此处写非零计数时的跳转逻辑,比如打开通知列表页
        }
    });

    // ... 省略原有角标显隐、文本赋值逻辑 ...

    // 删掉之前给textNotificationCount单独设置的setOnClickListener即可
}

内容的提问来源于stack exchange,提问作者Ritu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 15:54:21