Add badge count to navigation drawer hamburger icon – Android

NavigationDrawer provides easy access to menu functions. Sometimes the menu items have some actionable content available. To notify user that some actionable content is available it is ok to provide some badge over the hamburger icon.

ActionBarDrawerToggle provides a method setDrawerArrowDrawable() to provided custom drawer arrow drawable. Using this class we can provide a simple Badge which supports text to display any count.

Hamburger Icon without any Badge and Count

Use BadgeDrawerArrowDrawable to provide a badge and/or count to the hamburger icon.

package com.pcsalt.example.badgecountonnavigationmenu.badgeview

import android.content.Context
import android.graphics.*
import androidx.appcompat.graphics.drawable.DrawerArrowDrawable

class BadgeDrawerArrowDrawable(context: Context) : DrawerArrowDrawable(context) {
    private val backgroundPaint: Paint = Paint()
    private val textPaint: Paint = Paint()
    private var text: String? = null
    private var enabled = true

    companion object {
        // Fraction of the drawable's intrinsic size we want the badge to be.
        private const val SIZE_FACTOR = .3f
        private const val HALF_SIZE_FACTOR = SIZE_FACTOR / 2
    }

    init {
        backgroundPaint.color = Color.RED
        backgroundPaint.isAntiAlias = true
        textPaint.color = Color.WHITE
        textPaint.isAntiAlias = true
        textPaint.typeface = Typeface.DEFAULT_BOLD
        textPaint.textAlign = Paint.Align.CENTER
        textPaint.textSize = SIZE_FACTOR * intrinsicHeight
    }

    override fun draw(canvas: Canvas) {
        super.draw(canvas)
        if (!enabled) {
            return
        }
        val bounds = bounds
        val x = (1 - HALF_SIZE_FACTOR) * bounds.width()
        val y = HALF_SIZE_FACTOR * bounds.height()
        canvas.drawCircle(
            x,
            y,
            SIZE_FACTOR * bounds.width(),
            backgroundPaint
        )
        if (text == null || text!!.isEmpty()) {
            return
        }
        val textBounds = Rect()
        textPaint.getTextBounds(text, 0, text!!.length, textBounds)
        canvas.drawText(text!!, x, y + textBounds.height() / 2, textPaint)
    }

    fun setEnabled(enabled: Boolean) {
        if (this.enabled != enabled) {
            this.enabled = enabled
            invalidateSelf()
        }
    }

    fun isEnabled(): Boolean {
        return enabled
    }

    fun setText(text: String?) {
        if (this.text != text) {
            this.text = text
            invalidateSelf()
        }
    }

    fun getText(): String? {
        return text
    }

    var backgroundColor: Int
        get() = backgroundPaint.color
        set(color) {
            if (backgroundPaint.color != color) {
                backgroundPaint.color = color
                invalidateSelf()
            }
        }

    var textColor: Int
        get() = textPaint.color
        set(color) {
            if (textPaint.color != color) {
                textPaint.color = color
                invalidateSelf()
            }
        }
}

To use BadgeDrawerArrowDrawable with DrawerLayout following code snippet can help.

private lateinit var mDrawerToggle: ActionBarDrawerToggle

fun setupDrawerLayout() {
    val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
    mDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar,
        R.string.navigation_drawer_open, R.string.navigation_drawer_close)
    drawerLayout.addDrawerListener(mDrawerToggle)
    mDrawerToggle.syncState()
}

private fun setBadgeNavigationIcon() {
    supportActionBar?.themedContext?.let {
        if (!::badgeDrawerArrowDrawable.isInitialized) {
            badgeDrawerArrowDrawable = BadgeDrawerArrowDrawable(it)
        }

    mDrawerToggle.drawerArrowDrawable = badgeDrawerArrowDrawable
    badgeDrawerArrowDrawable.backgroundColor =
ContextCompat.getColor(this, R.color.badge_color)
    }
}

To display only Badge icon enable the badge and set the text to null.

badgeDrawerArrowDrawable.setEnabled(true)
badgeDrawerArrowDrawable.setText(null)

To display Badge icon with count

badgeDrawerArrowDrawable.setEnabled(true)
badgeDrawerArrowDrawable.setText("$count")

Download Source Code

The complete source code is pushed in GitHub repo. Browse it by clicking on the octocat icon.