AppCompat 23.2 использует VectorDrawableCompat с RemoteViews (AppWidget) в API<21
У меня есть AppWidget, и я хотел бы использовать в нем VectorDrawables также на устройствах, предшествующих Lollipop. VectorDrawableCompat не будет работать с RemoteViews, которые я создаю.
Чтобы уменьшить размер APK моего приложения, я не хочу добавлять альтернативные версии моих чертежей в формате PNG для более старых платформ API.
Как я могу это сделать?
2 ответа
ОБНОВЛЕНИЕ 22/10/2017
Как отметил @user924, теперь доступ к AppCompatDrawableManager ограничен его собственной библиотекой. ContextCompat.getDrawable (...) должен сделать свое дело.
ОБНОВЛЕНИЕ 05/09/2016
Как отметил @kirill-kulakov в своем ответе, последние обновления библиотеки поддержки ограничивали видимость TintContextWrapper собственным пакетом. Я обновляю свой ответ, чтобы удалить неправильный код, но, пожалуйста, поблагодарите Кирилла за исправление!
VectorDrawable и RemoteViews перед леденцом на палочке
Вы можете избежать добавления альтернативных растеризованных версий ваших векторных графических ресурсов простым взломом: используйте AppCompat TintResources через TintContextWrapper, используя AppCompatDrawableManager, используя ContextCompat.
TintResources AppCompatDrawableManager ContextCompat - это класс, который, помимо прочего, на устройствах, предшествующих Lollipop, анализирует XML-файлы VectorDrawable и преобразует их в экземпляры VectorDrawableCompat, которые можно использовать вплоть до API 7.
Затем, когда у вас будет экземпляр VectorDrawableCompat, растеризуйте его в растровое изображение. Позже вы будете использовать это растровое изображение в удаленном ImageView.
Прежде чем мы начнем: Библиотека AppCompat
Убедитесь, что вы используете Android Studio 2.0+ и настроили свое приложение build.gradle
файл следующим образом:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.3.0'
}
Обновите свой 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);
}
Рекомендации
- Исходный код ContextCompat
- AppCompat v23.2 Криса Банеса - "Возраст векторов" представляет блог VectorDrawableCompat и рассказывает о том, как AppCompat использует их для работы на устройствах до Lollipop.
Следующий метод преобразует 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;
}