DrawableRes是否为VectorDrawable的检查

6

我有一个方法,可以将VectorDrawable设置为TextView和Button的DrawableLeft、DrawableRight等,但我希望它也适用于普通的Drawable。那么,有没有一种方法可以检查DrawableRes的类型,或者应该使用try/catch? 该方法如下:

public static void setViewDrawables(@NonNull View view, @DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
    final Resources resources = view.getResources();
    Drawable vectorDrawableLeft = left != 0 ? VectorDrawableCompat.create(resources, left, view.getContext().getTheme()) : null;
    Drawable vectorDrawableTop = top != 0 ? VectorDrawableCompat.create(resources, top, view.getContext().getTheme()) : null;
    Drawable vectorDrawableRight = right != 0 ? VectorDrawableCompat.create(resources, right, view.getContext().getTheme()) : null;
    Drawable vectorDrawableBottom = bottom != 0 ? VectorDrawableCompat.create(resources, bottom, view.getContext().getTheme()) : null;

    if (view instanceof Button) {
        ((Button) view).setCompoundDrawablesWithIntrinsicBounds(vectorDrawableLeft, vectorDrawableTop, vectorDrawableRight, vectorDrawableBottom);
    }
    else if (view instanceof TextView) {
        ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(vectorDrawableLeft, vectorDrawableTop, vectorDrawableRight, vectorDrawableBottom);
    } else {
        Log.e("ERROR: ViewUtils", "Can't do setCompoundDrawablesWithIntrinsicBounds on " + view.getClass().getName());
    }
}

2
所以你想要 android.support.v7.content.res.AppCompatResources - pskink
1
可以了,谢谢!我刚刚用AppCompatResources.getDrawable(view.getContext(), left)替换了VectorDrawableCompat.create(resources, left, view.getContext().getTheme()) - Vladimir Jovanović
还有一个android.support.v4.content.res.ResourcesCompat,但我不知道它是否也能正常工作,你可以去试试看... - pskink
1个回答

5

总结对答案的评论。据我所知,没有简便的方法来确定DrawableRes是否指向VectorDrawable。如果有人知道,请写下来。但是为了解决我的问题,使用如@pskink所建议的android.support.v7.content.res.AppCompatResources就足够了。因此现在的方法看起来像:

public static void setViewDrawables(@NonNull View view, @DrawableRes int left, @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
    Drawable vectorDrawableLeft = left != 0 ? AppCompatResources.getDrawable(view.getContext(), left) : null;
    Drawable vectorDrawableTop = top != 0 ? AppCompatResources.getDrawable(view.getContext(), top) : null;
    Drawable vectorDrawableRight = right != 0 ? AppCompatResources.getDrawable(view.getContext(), right) : null;
    Drawable vectorDrawableBottom = bottom != 0 ? AppCompatResources.getDrawable(view.getContext(), bottom) : null;

    if (view instanceof Button) {
        ((Button) view).setCompoundDrawablesWithIntrinsicBounds(vectorDrawableLeft, vectorDrawableTop, vectorDrawableRight, vectorDrawableBottom);
    } else if (view instanceof TextView) {
        ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(vectorDrawableLeft, vectorDrawableTop, vectorDrawableRight, vectorDrawableBottom);
    } else {
        Log.e("ERROR: ViewUtils", "Can't do setCompoundDrawablesWithIntrinsicBounds on " + view.getClass().getName());
    }
}

更新:

android.support.v7.widget.AppCompatDrawableManager 中有一个方法 boolean isVectorDrawable(@NonNull Drawable d),用于检查 Drawable 是否为 VectorDrawable,但它将 Drawable 作为参数而不是 DrawableRes。它看起来像这样:

private static boolean isVectorDrawable(@NonNull Drawable d) {
    return d instanceof VectorDrawableCompat
          || PLATFORM_VD_CLAZZ.equals(d.getClass().getName());
}

1
如果你想知道他们是如何做到的,只需使用调试器进入AppCompatResources.getDrawable,并检查在何时/如何调用VectorDrawableCompat.create以创建VectorDrawableCompat - pskink
isVectorDrawable方法之后,有一个名为VdcInflateDelegate的私有静态类,它实现了InflateDelegate接口,用于解析VectorDrawableCompat对象。 - pskink
@pskink 是的,但是你可以看到这是一个try/catch方法,我在问题中问是否有其他更简洁的方法。在那个方法中,他们试图创建VectorDrawable,如果不起作用,则不是VectorDrawable。 - Vladimir Jovanović
没有调试方法loadDrawableFromDelegates,就在String tagName = parser.getName()之后。 - pskink
1
简而言之:他们首先检查资源名称是否以“xml”结尾,如果是,则尝试获取根元素,然后如果它是“vector”,则调用“VectorDrawableCompat.create”方法。 - pskink

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接