Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách hiển thị số lượng thông báo (Badge) trên icon Toolbar Android

Giới thiệu

Hiển thị số lượng thông báo (notification badge/count) trên icon trong Toolbar/ActionBar. Android không có API chuẩn cho badge trên toolbar icon, phải tự custom layout.

Cách làm: Custom Toolbar với Badge TextView

1. res/drawable/item_count.xml (Background badge tròn/bo tròn)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="https://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="8dp" />
    <solid android:color="#2196F3" />
    <stroke android:width="1dp" android:color="#FFF" />
    <padding android:bottom="2dp" android:left="6dp" android:right="6dp" android:top="2dp" />
</shape>

2. activity_main.xml - Toolbar custom

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginEnd="16dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:text="Notify Me"
                android:textAppearance="@style/TextAppearance.AppCompat.Medium"
                android:textColor="#FFF"
                android:textStyle="bold" />

            <RelativeLayout
                android:id="@+id/notificationBadge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true">

                <RelativeLayout
                    android:id="@+id/badgeLayout"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:paddingTop="8dp">

                    <ImageView
                        android:layout_width="36dp"
                        android:layout_height="36dp"
                        android:src="@drawable/ic_notifications" />

                </RelativeLayout>

                <TextView
                    android:id="@+id/tvBadgeNumber"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignTop="@id/badgeLayout"
                    android:layout_alignEnd="@id/badgeLayout"
                    android:background="@drawable/item_count"
                    android:text="0"
                    android:textColor="#FFF"
                    android:textSize="12sp"
                    android:textStyle="bold"
                    android:visibility="gone" />

            </RelativeLayout>

        </RelativeLayout>
    </androidx.appcompat.widget.Toolbar>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_margin="16dp"
        android:onClick="createNotification"
        android:text="Tạo thông báo (tăng badge)" />

</RelativeLayout>

3. MainActivity.java

package com.example.toolbarbadge;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private static final String CHANNEL_ID = "badge_channel";
    private TextView tvBadgeNumber;
    private int notificationCount = 0;

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

        tvBadgeNumber = findViewById(R.id.tvBadgeNumber);
        // Setup Toolbar nếu cần
        // setSupportActionBar(findViewById(R.id.toolbar));
    }

    public void createNotification(View view) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(
                this, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationManager manager = getSystemService(NotificationManager.class);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setContentTitle("Thông báo #" + (notificationCount + 1))
                .setContentText("Badge sẽ tăng lên")
                .setContentIntent(pendingIntent)
                .setAutoCancel(true);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID, "Badge Demo", NotificationManager.IMPORTANCE_DEFAULT);
            manager.createNotificationChannel(channel);
        }

        manager.notify((int) System.currentTimeMillis(), builder.build());

        // Cập nhật badge count trên toolbar
        notificationCount++;
        updateBadge();
    }

    private void updateBadge() {
        if (notificationCount > 0) {
            tvBadgeNumber.setText(String.valueOf(notificationCount));
            tvBadgeNumber.setVisibility(View.VISIBLE);
        } else {
            tvBadgeNumber.setVisibility(View.GONE);
        }
    }

    // Giảm badge khi mở app / xóa thông báo
    @Override
    protected void onResume() {
        super.onResume();
        // Logic thực tế: query số thông báo chưa đọc từ database/prefs
        // notificationCount = getUnreadCount();
        // updateBadge();
    }
}

Lưu ý quan trọng

  • Không phải Notification Badge hệ thống: Đây là badge custom trên Toolbar. Notification Badge hệ thống (chấm đỏ trên icon app launcher) được quản lý bởi Launcher, không thể tùy chỉnh số lượng từ app (chỉ bật/tắt qua Channel).
  • Đồng bộ số lượng: Cần lưu trữ count (SharedPreferences, Database) và cập nhật khi: tạo notif mới, user đọc, user xóa, app mở.
  • ShortcutBadger (Thư viện cũ): Hỗ trợ badge trên icon launcher cho một số launcher (Samsung, HTC, Sony...), nhưng **không còn maintain** và không hoạt động trên Android 8.0+ standard.

Notification Badge hệ thống (App Icon Badge)

Android 8.0+ tự động hiển thị chấm đỏ trên icon app khi có notification active trong channel có setShowBadge(true) (mặc định).

// Trong createNotificationChannel()
channel.setShowBadge(true); // Mặc định true
// Không thể set số lượng cụ thể, chỉ có/không có chấm.