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.
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.