1

For my application, I have different in-App notifications for news in the different navigation drawer sections. I want to be able to change the icons in the navigation drawer to represent the number of unread notifications in each category, without having to make an icon for each and every number for app-size related reasons.

Basically, I need an approach to creating a drawable based on my standard icon for the category, that can also show a number on top (in the lower right-hand corner of the icon to be specific).

My best lead was creating a custom drawable, that also takes a parameter for the number to show and overwrites the on draw method, but can't seem to find an example with an image and text/ a number on top.

Edit: I'm sorry for the broad question, but I've gotten desperate over the last few days, I hope it's not too broad and still conforms the rules.

Nicola Gallazzi
  • 7,897
  • 6
  • 45
  • 64
Jujinko
  • 319
  • 3
  • 21
  • You can have a look at this post, i believe this is what you are looking for -https://stackoverflow.com/questions/32563200/how-to-set-unread-notification-count-in-navigationview-of-drawerlayout – James Fernandes Jan 28 '19 at 13:21
  • Sadly not, in my case the notification counter is intended to be on the MenuIcon – Jujinko Jan 28 '19 at 13:53

1 Answers1

1

You can create your own custom view with a custom xml layout and generate a bitmap for the layout at runtime. The layout may be like the one below:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

    <ImageView android:layout_width="96dp"
               android:layout_height="96dp"
               android:src="@drawable/ic_message" app:layout_constraintEnd_toEndOf="parent"
               android:layout_marginEnd="8dp" app:layout_constraintStart_toStartOf="parent"
               android:layout_marginStart="8dp" android:layout_marginTop="8dp"
               app:layout_constraintTop_toTopOf="parent" android:layout_marginBottom="8dp"
               app:layout_constraintBottom_toBottomOf="parent" android:id="@+id/imageView"/>
    <TextView
            android:id="@+id/tvCounter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="@+id/imageView"
            tools:text="1"
            android:textSize="16sp"
            android:textStyle="bold" app:layout_constraintStart_toStartOf="@+id/imageView"
            app:layout_constraintEnd_toEndOf="@+id/imageView" app:layout_constraintHorizontal_bias="0.9"
            app:layout_constraintBottom_toBottomOf="@+id/imageView" app:layout_constraintVertical_bias="0.100000024"
            android:textColor="@android:color/white"/>

</android.support.constraint.ConstraintLayout>

Then, create a custom view that extends ConstraintLayout. In this view define an "init" method to inflate your custom layout like below, where custom_counter_layout is the name of the layout your created via xml:

 private void init() {
        inflate(getContext(), R.layout.custom_counter_layout, this);
        this.tvCounter = findViewById(R.id.tvCounter);
    }

At this point, you can call this "init" method in the CustomView constructor, something like:

 public CustomCounterLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomCounterLayout(Context context) {
        super(context);
        init();
    }

    public CustomCounterLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

Then, define a "getBitmap()" method that generates a bitmap from the view layout:

public Bitmap getBitmap(){
        DisplayMetrics displayMetrics = new DisplayMetrics();
        ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
        layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
        buildDrawingCache();
        Bitmap bitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmap);
        draw(canvas);
        //return the bitmap
        return bitmap;
    }

In addition, define also a "setTvCounter" convenience method to set the number for the view from the external:

  public void setTvCounter(int counter) {
        tvCounter.setText(String.valueOf(counter));
    }

This, should be the CustomCounterLayout class when you're done:

package com.ngallazzi.stacktests;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.support.constraint.ConstraintLayout;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.TextView;

/**
 * StackTests
 * Created by Nicola on 1/28/2019.
 * Copyright © 2019 Zehus. All rights reserved.
 */
public class CustomCounterLayout extends ConstraintLayout {
    private TextView tvCounter;

    public CustomCounterLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomCounterLayout(Context context) {
        super(context);
        init();
    }

    public CustomCounterLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        inflate(getContext(), R.layout.custom_counter_layout, this);
        this.tvCounter = findViewById(R.id.tvCounter);
    }

    public Bitmap getBitmap(){
        DisplayMetrics displayMetrics = new DisplayMetrics();
        ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
        layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
        buildDrawingCache();
        Bitmap bitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmap);
        draw(canvas);
        //return the bitmap
        return bitmap;
    }

    public void setTvCounter(int counter) {
        tvCounter.setText(String.valueOf(counter));
    }
}

In order to set your layout with the right count of items, use the custom view in your activity layout, then use the setTvCounter method to update the custom view. Once you've done that, use the getBitmap() method to generate the drawable you'll bind to your navigation drawer layout.

Nicola Gallazzi
  • 7,897
  • 6
  • 45
  • 64