0

I'm having trouble getting BadgeDrawable to work.

There is no problem using it with BottomNavigationView

navView.setupWithNavController(navController)
val badge = navView.getOrCreateBadge(R.id.navigation_home)
badge.number = 12

But when I want to use it on other elements it wont show up. Like this:

val badgeDrawable = BadgeDrawable.create(context!!)
badgeDrawable.number = 32
BadgeUtils.attachBadgeDrawable(badgeDrawable, textView, root.findViewById(R.id.frame_layout))

I'm using the FrameLayout only because this issue fix seems to be not shipped yet.

Layout:

<FrameLayout
    android:id="@+id/frame_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="8dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <ImageView
        android:id="@+id/text_home"
        android:src="@drawable/ic_home_black_24dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAlignment="center"
        android:textSize="20sp" />
</FrameLayout>

I'm using the latest possible library version: 'com.google.android.material:material:1.2.0-rc01'

I've tried different methods. No luck though. Is there a secret to it which I'm missing?

Here is a git repo with the project (as simple as possible): https://github.com/marcinkunert/badgeissue

badge drawable not showing

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
Marcin Kunert
  • 5,596
  • 5
  • 26
  • 52

3 Answers3

5

You can use something like:

 <FrameLayout
    android:clipChildren="false"
    android:clipToPadding="false">


    <ImageView
        android:id="@+id/text_home"
        .../>

</FrameLayout>

and in your code:

    ImageView imageView = findViewById(R.id.text_home);
    imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            BadgeDrawable badgeDrawable = BadgeDrawable.create(context);
            badgeDrawable.setNumber(32);
            badgeDrawable.setBadgeGravity(BadgeDrawable.TOP_END);
            BadgeUtils.attachBadgeDrawable(badgeDrawable, imageView, findViewById(R.id.layout));
            imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • Hi, can you help me to solve my question https://stackoverflow.com/questions/73597146/how-to-add-badge-on-hamburger-navigation-menu-icon ? – Nima Khalili Sep 04 '22 at 06:12
1

For now I've came up with this function:

fun addBadgeDrawable(count: Int, target: View, parent: FrameLayout, context: Context) {
    target.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            val badgeDrawable = BadgeDrawable.create(context)
            badgeDrawable.number = count
            badgeDrawable.setBoundsFor(target, parent)
            parent.foreground = badgeDrawable
            target.viewTreeObserver.removeOnGlobalLayoutListener(this)
        }
    })
}

Unfortunately the BadgeUtils are not working for me at the moment.

Here is the layout:

<FrameLayout
    android:id="@+id/issues_button_container"
    android:layout_width="wrap_content"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:layout_height="wrap_content"
    android:layout_marginRight="4dp"
    android:layout_gravity="right"
    android:paddingTop="12dp"
    android:paddingBottom="12dp"
    android:paddingEnd="12dp">

    <ImageView
        android:id="@+id/issues_button"
        android:layout_gravity="left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_warning_black_24dp"
        android:tint="@color/c_gold" />
</FrameLayout>

I suspect there will be issues with this solution in the near future. I'll try to update this answer if I'll find any.

The solution is mostly inspired by this answer.

Marcin Kunert
  • 5,596
  • 5
  • 26
  • 52
0

Use the code from this answer and the xml from this answer

 FrameLayout frameLayout = findViewById(R.id.frameLayout)

ImageView imageView = findViewById(R.id.ivIcon);
imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        BadgeDrawable badgeDrawable = BadgeDrawable.create(context);
        badgeDrawable.setNumber(32);
        badgeDrawable.setBadgeGravity(BadgeDrawable.BOTTOM_END);
        BadgeUtils.attachBadgeDrawable(badgeDrawable, imageView, framelayout);
        imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
});

Depending on the gravity of your badge drawable, set padding accordingly. In my case, i want the badge to show at the bottom end.

          <FrameLayout
                android:id="@+id/frameLayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clipChildren="false"
                android:clipToPadding="false"
                android:layout_centerInParent="true"
                android:layout_gravity="end"
                android:paddingBottom="9dp"
                android:paddingEnd="13dp"
                >

                <ImageView
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:id="@+id/ivIcon"            
                    android:layout_gravity="center"
                    app:srcCompat="@drawable/ic_icon" />

            </FrameLayout>
Ayia
  • 146
  • 6