我有一个 AppWidget,我也想在棒棒糖之前的设备上使用 VectorDrawables。VectorDrawableCompat 不适用于我创建的 RemoteViews。
为了减小我的应用 APK 大小,我不想为旧 API 平台添加我的 drawable 的替代 PNG 版本。
我怎样才能做到这一点?
我有一个 AppWidget,我也想在棒棒糖之前的设备上使用 VectorDrawables。VectorDrawableCompat 不适用于我创建的 RemoteViews。
为了减小我的应用 APK 大小,我不想为旧 API 平台添加我的 drawable 的替代 PNG 版本。
我怎样才能做到这一点?
更新 22/10/2017
正如@user924 所指出的,现在AppCompatDrawableManager访问仅限于其自己的库。 ContextCompat.getDrawable(...)应该可以解决问题。
更新 05/09/2016
正如@kirill-kulakov 在其回答中指出的那样,支持库的最新更新将 TintContextWrapper 的可见性限制在它自己的包中。我正在更新我的答案以删除不正确的代码,但请感谢 Kirill 的更正!
您可以通过简单的技巧避免添加矢量可绘制资源的替代光栅化版本:使用AppCompat TintResources通过TintContextWrapper 使用AppCompatDrawableManager使用ContextCompat。
TintResources AppCompatDrawableManager ContextCompat是在棒棒糖之前的设备上解析VectorDrawable的 XML 文件并将它们转换为可一直使用到 API 7 的VectorDrawableCompat实例的类。
然后,一旦你有一个VectorDrawableCompat实例,就将它光栅化到一个位图上。稍后您将在远程ImageView中使用此位图。
确保您使用的是 Android Studio 2.0+ 并已build.gradle
按如下方式配置您的应用文件:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.3.0'
}
首先:不要在你的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);
}
以下方法将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;
}