AppCompat 23.2在API <21上使用带有RemoteViews(AppWidget)的VectorDrawableCompat

我有一个AppWidget,我也想在它之前的棒棒糖设备中使用VectorDrawables。 VectorDrawableCompat不能与我创build的RemoteViews一起使用。

为了保持我的应用程序APK的大小,我不想为旧API平台添加我的drawable的替代PNG版本。

我怎样才能做到这一点?

Solutions Collecting From Web of "AppCompat 23.2在API <21上使用带有RemoteViews(AppWidget)的VectorDrawableCompat"

更新22/10/2017

正如@ user924所指出的那样, AppCompatDrawableManager访问被限制在它自己的库中。 ContextCompat.getDrawable(…)应该做的伎俩。

更新05/09/2016

正如@ kirill-kulakov在回答中所指出的那样,支持库的最新更新将TintContextWrapper的可见性限制在它自己的包中。 我正在更新我的答案,以删除不正确的代码,但请感谢基里尔的更正!

VectorDrawable和RemoteViews之前的棒棒糖

您可以避免通过简单的黑客手段添加vector可绘制资源的替代栅格化版本:使用 AppCompatDrawableManager,使用ContextCompat, 通过TintContextWrapper 使用AppCompat TintResources

TintResources AppCompatDrawableManager ContextCompat是在Lollipop之前的设备中parsingVectorDrawable的XML文件并将其转换为VectorDrawableCompat实例的类,可以一直使用到API 7。

然后,一旦你有一个VectorDrawableCompat实例,将其栅格化到一个位图上。 您稍后将在远程ImageView中使用此位图。

开始之前:AppCompat库

确保您使用的是Android Studio 2.0+,并已经configuration了您的应用程序build.gradle文件,如下所示:

 android { defaultConfig { vectorDrawables.useSupportLibrary = true } } dependencies { compile 'com.android.support:appcompat-v7:23.3.0' } 

更新你的AppWidgetProvider

首先:不要在你的RemoteViews布局文件中设置你的vector可绘制资源( android:srcapp:srcCompat都不会工作)。 你必须以编程方式设置它们。

AppWidgetProvider类中,根据API级别设置vector资源或栅格化版本:

 RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { remoteViews.setImageViewResource(R.id.imageView, R.drawable.vector); } else { Drawable d = ContextCompat.getDrawable(context, R.drawable.vector); Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); d.setBounds(0, 0, c.getWidth(), c.getHeight()); d.draw(c); remoteViews.setImageViewBitmap(R.id.imageView, b); } 

参考

  • ContextCompat 源代码
  • Chris Banes的AppCompat v23.2 – vector博客文章的年龄介绍了VectorDrawableCompat,并解释了AppCompat用来使他们在前棒棒糖设备上工作的黑客。

下面的方法将vector drawable到位图之前,这应该做的伎俩。

 public static BitmapDrawable vectorToBitmapDrawable(Context ctx, @DrawableRes int resVector) { return new BitmapDrawable(ctx.getResources(), vectorToBitmap(ctx, resVector)); } public static Bitmap vectorToBitmap(Context ctx, @DrawableRes int resVector) { Drawable drawable = AppCompatDrawableManager.get().getDrawable(ctx, resVector); Bitmap b = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); drawable.setBounds(0, 0, c.getWidth(), c.getHeight()); drawable.draw(c); return b; }