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.