1

I want to display notification badge on menu item. My code is

onPrepareOptionsMenu()

    int cartSize = MyCart.getCartSize();
    MenuItem cartItem = menu.findItem(R.id.toolbar_ic_cart);

    if (cartSize > 0) {
        LayerDrawable icon = (LayerDrawable) cartItem.getIcon();
        NotificationBadgeCount.setBadgeCount(this, icon, String.valueOf(cartSize));
    } else {
        cartItem.setIcon(R.drawable.ic_cart_empty);
    }

menu/toolbar_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/toolbar_ic_search"
        android:title="Search"
        android:icon="@drawable/ic_search"
        app:showAsAction="always" />

    <item
        android:id="@+id/toolbar_ic_cart"
        android:title="Cart"
        android:icon="@drawable/ic_cart_menu"
        app:showAsAction="always" />

</menu>

@drawable/ic_cart_menu

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:drawable="@drawable/ic_cart_full"
        android:gravity="center" />

    <!-- set a place holder Drawable so android:drawable isn't null -->
    <item
        android:id="@+id/ic_badge"
        android:drawable="@drawable/ic_cart_empty" />

</layer-list>

This code was working fine for me. But after upgrading support libraries, I am getting error on all devices except Marshmallow

Error in following line

LayerDrawable icon = (LayerDrawable) cartItem.getIcon();

Error on Lollipop.

java.lang.ClassCastException: android.support.v4.graphics.drawable.DrawableWrapperLollipop cannot be cast to android.graphics.drawable.LayerDrawable

Error on Kitkat.

java.lang.ClassCastException: android.support.v4.graphics.drawable.DrawableWrapperKitkat cannot be cast to android.graphics.drawable.LayerDrawable
Hafiz Muneeb
  • 307
  • 8
  • 15

2 Answers2

1

It is because DrawableWrapperLollipop extends DrawableWrapperKitkat and DrawableWrapperKitkat to some other older vesrion and so on.. But the parent class is Drawable and not LayerDrawable. That is the reason for exception.

Anurag Singh
  • 6,140
  • 2
  • 31
  • 47
1

Those wrapper classes all implement DrawableWrapper, from which you can get the original drawable:

import android.support.v4.graphics.drawable.DrawableWrapper;

...

    LayerDrawable icon = null;
    Drawable drawable = cartItem.getIcon();
    if (drawable instanceof DrawableWrapper) {
        drawable = ((DrawableWrapper)drawable).getWrappedDrawable();
    }
    icon = (LayerDrawable) drawable;
kris larson
  • 30,387
  • 5
  • 62
  • 74
  • can't find method getWrappedDrawable(); – Hafiz Muneeb Feb 09 '17 at 14:25
  • `import android.support.v4.graphics.drawable.DrawableWrapper;` – kris larson Feb 09 '17 at 14:38
  • it was `android.graphics.drawable.DrawableWrapper;` – Hafiz Muneeb Feb 10 '17 at 05:45
  • `import android.support.v4.graphics.drawable.DrawableWrapper;` doesn't exist, `android.graphics.drawable.DrawableWrapper;` doesn't work in my case – CoolMind Nov 30 '18 at 07:58
  • @CoolMind A lot has changed since I wrote this answer. You're probably on the `androidx` packages now. `DrawableWrapper` is marked `@hide`, so even though it's public, Google doesn't really want you using it. You may need to write some version specific code (`if (BuildConfig.VERSION_CODE < VersionCodes.MARSHMALLOW)` etc. --- I forgot the exact syntax) to check whether to cast and which cast to use. And you might need to go into the debugger on each version to find out the actual class names. Worst case you may need to use reflection code to get at the `LayerDrawable`. – kris larson Nov 30 '18 at 21:39
  • @krislarson, thank you! Sorry, I forgot that wrote an answer in https://stackoverflow.com/a/53554149/2914140 for this case (`import android.support.v7.graphics.drawable.DrawableWrapper;` or `android.support.v4.graphics.drawable.WrappedDrawable`). – CoolMind Dec 03 '18 at 07:03