无法在 android 中将 Drawable 转换为 LayerDrawable

Unable to cast Drawable to LayerDrawable in android

我想在菜单项上显示通知标志。我的密码是

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>

这段代码对我来说工作正常。但是在升级支持库之后,我在除 Marshmallow

之外的所有设备上都出现错误

下一行错误

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

Lollipop 出错。

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

Kitkat 出错。

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

这是因为 DrawableWrapperLollipopDrawableWrapperKitkatDrawableWrapperKitkat 扩展到其他一些旧版本等等。但是父 class 是 Drawable 并且不是 LayerDrawable。这就是例外的原因。

那些包装器 类 都实现了 DrawableWrapper,从中你可以得到原始的 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;