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

ara*_*aks 29 android android-appcompat remoteview android-support-library android-vectordrawable

我有一个AppWidget,我想在Lollipop前设备上使用VectorDrawables.VectorDrawableCompat不能与我创建的RemoteViews一起使用.

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

我怎样才能做到这一点?

ara*_*aks 51

更新22/10/2017

正如@ user924所述,现在AppCompatDrawableManager访问仅限于自己的库. ContextCompat.getDrawable(...)应该可以解决问题.

更新05/09/2016

正如@ kirill-kulakov在其回答中所指出的,支持库的最新更新限制了TintContextWrapper对其自己的包的可见性.我正在更新我的答案以删除不正确的代码,但请感谢Kirill的更正!

VectorDrawable和RemoteViews前Lollipop

您可避免增加你的矢量绘图资源的替代版本光栅化了一个简单的黑客:使用程序兼容性TintResources通过TintContextWrapper 使用AppCompatDrawableManager使用ContextCompat.

TintResources AppCompatDrawableManager ContextCompat是一个类,在Lollipop之前的设备上,解析 VectorDrawable的XML文件并将它们转换为可以一直使用到API 7的 VectorDrawableCompat实例.

然后,一旦你有了一个VectorDrawableCompat实例,就把它栅格化到一个Bitmap上.稍后您将在远程ImageView中使用此位图.


在开始之前:AppCompat Library

确保您使用的是Android Studio 2.0+,build.gradle并按如下方式配置了您的应用文件:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
  compile 'com.android.support:appcompat-v7:23.3.0'
}
Run Code Online (Sandbox Code Playgroud)


更新您的AppWidgetProvider

首先:不要在RemoteViews布局文件中设置矢量可绘制资源(既android:src不会也app:srcCompat不会起作用).您必须以编程方式设置它们.

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

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);
}
Run Code Online (Sandbox Code Playgroud)


参考

  • TintContextWrapper在android.support.v7.widget中不公开; 无法从外部包裹访问 (2认同)

Kir*_*kov 8

以下方法将之前转换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;
}
Run Code Online (Sandbox Code Playgroud)